LAN문제를 풀다가 두가지 걸림돌이 있어서 질문드립니다.
지금 C++의 자료형과 문법을 약간 쓰고 있는데 C++ 지식 없습니다...
(처음 질문해서 설명에 실수가 있을 수도 있습니다. 이해가 안되시면 물어봐주세요.)
시간 초과
지금 시간초과로 계속 틀리고 있는데 제 생각에는 더 이상 연산 과정이 줄어드는 방법이 없다고 생각하는데
이러면 알고리즘을 갈아 엎는게 맞는 건가요...
오차
예제 출력을 하면 10-7 이상에서 오차가 생기는데, 원인을 모르겠습니다. 예상으론 제 루트 계산법이 문제이거나
아니면 프림 알고리즘을 잘못 응용해서 최솟값이 아닌 값이 나오는 것 같은데 건물 사이의 거리가 정수가 아니라서
계산할 엄두가.... 안 나네요...
#include <stdio.h>#define SQR_LEN(x, y) ((x)*(x))+((y)*(y))floatSQRT(floatval){floattotal=1;for(inti=0;i<8;i++){total=(total+(val/total))/2;}returntotal;}intmain(){intnum_case;floattotal_length[50];//준비 과정scanf("%d",&num_case);for(inti=0;i<num_case;i++)//테스트 케이스(50번 이하) 루프{intnum_build,num_cable_installed;intp_build[500][2];//건물의 좌표inttemp[3];chargraph_build[500][500]={0,};//0: nonconnected c: connected a: already connectedboolconnected_build[500]={0,};//첫 줄은 건물 개수(500개 이하)와 설치된 케이블 개수(2000개 이하)scanf("%d %d",&num_build,&num_cable_installed);//건물들의 x좌표for(intj=0;j<num_build;j++){scanf("%d ",&p_build[j][0]);}//건물들의 y좌표(좌표는 전부 1000이하)for(intj=0;j<num_build;j++){scanf("%d ",&p_build[j][1]);}//설치된 케이블 하나당 연결된 건물...for(intj=0;j<num_cable_installed;j++){scanf("%d %d",&temp[0],&temp[1]);graph_build[temp[0]][temp[1]]=graph_build[temp[1]][temp[0]]='a';}//해결 과정//프림 알고리즘 응용//출발점 하나를 지정한다.//만약 지금 이어진 노드가 이미 이어진 케이블이 있으면 그 노드도 연결시킨다.//기본적으론 지나간 점들에 이어진 에지 중 최솟값을 다음 이어진 노드로 정한다.//출발점은 건물 0번//가장 큰 루프는 전체 건물이 케이블로 이어져 있을 때 탈출//연결된 노드가 새로 생기면 루프는 지금 노드에서 이미 설치된 케이블이 있는지 확인한다.//있으면 자동으로 트리에 연결한다.//루프는 지금 지나간 모든 노드에서 가장 최소 에지를 찾는다//단 시작노드와 끝노드가 전부 지나간 노드인 경우는 제외한다.(트리에 속해있으므로)//새로 이어질 최소 에지는 총 설치해야할 케이블 길이에 추가한다.connected_build[0]=true;//출발점 지정total_length[i]=0;while(true){//연결된 노드 중 이미 설치된 케이블이 있는지 확인하는 루프while(true){boolis_end=true;for(intj=0;j<num_build;j++){for(intk=j;k<num_build;k++){if((connected_build[j]||connected_build[k])&&graph_build[j][k]=='a'){graph_build[j][k]='c';connected_build[k]=connected_build[j]=true;is_end=false;break;}}}if(is_end)break;}//모든 건물이 연결되어 있는가boolis_all_connect=true;for(intj=0;j<num_build;j++){if(!connected_build[j]){is_all_connect=false;break;}}if(is_all_connect)break;//해결 루프 탈출else{//최소 에지 찾기temp[2]=0;//temp: [0] = 최소 에지의 시작노드, [1] = 최소 에지의 끝노드, [2] = 최소 에지의 길이의 제곱for(intj=0;j<num_build;j++){//이어진 노드 찾기for(intk=j;k<num_build;k++){if(connected_build[j]||connected_build[k]){if(connected_build[j]&&connected_build[k])//이미 연결된 노드는 제외continue;if(!temp[2])//temp값 초기화{temp[0]=j;temp[1]=k;temp[2]=SQR_LEN(p_build[k][0]-p_build[j][0],p_build[k][1]-p_build[j][1]);continue;}if(temp[2]>SQR_LEN(p_build[k][0]-p_build[j][0],p_build[k][1]-p_build[j][1])){temp[0]=j;temp[1]=k;temp[2]=SQR_LEN(p_build[k][0]-p_build[j][0],p_build[k][1]-p_build[j][1]);}}}}//최소 에지에 케이블 연결graph_build[temp[0]][temp[1]]='c';connected_build[temp[0]]=connected_build[temp[1]]=true;total_length[i]+=SQRT((float)temp[2]);}}//해결 과정 end}//출력: 각 케이스 당 설치할 케이블들의 최소 합for(inti=0;i<num_case;i++){printf("%.12f\n",total_length[i]);}return0;}
wraithkim
LAN문제를 풀다가 두가지 걸림돌이 있어서 질문드립니다.
지금 C++의 자료형과 문법을 약간 쓰고 있는데 C++ 지식 없습니다...
(처음 질문해서 설명에 실수가 있을 수도 있습니다. 이해가 안되시면 물어봐주세요.)
시간 초과
지금 시간초과로 계속 틀리고 있는데 제 생각에는 더 이상 연산 과정이 줄어드는 방법이 없다고 생각하는데
이러면 알고리즘을 갈아 엎는게 맞는 건가요...
오차
예제 출력을 하면 10-7 이상에서 오차가 생기는데, 원인을 모르겠습니다. 예상으론 제 루트 계산법이 문제이거나
아니면 프림 알고리즘을 잘못 응용해서 최솟값이 아닌 값이 나오는 것 같은데 건물 사이의 거리가 정수가 아니라서
계산할 엄두가.... 안 나네요...
9년 전