暴力枚举点,然后跑最小生成树得到这些点时的最小边权之和。
由于枚举的时候本来就是按照字典序的,不需要额外判。
错误原因:要求输出的结尾不能有空格。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 using namespace std; 5 bool ok[16],ok2[16]; 6 bool vis[16]; 7 int num,n,m; 8 int a[16],b[16][16]; 9 vector<int> vec; 10 double anss; 11 int dis[16]; 12 void prim() 13 { 14 memset(vis,0,sizeof(vis)); 15 memset(dis,0x3f,sizeof(dis)); 16 int i,j,s,sum=0,mina,minid,s1=0; 17 for(s=1;s<=n;s++) 18 if(ok[s]) 19 break; 20 vis[s]=1; 21 dis[s]=0; 22 for(i=s+1;i<=n;i++) 23 if(ok[i]) 24 dis[i]=b[s][i]; 25 for(i=1;i<m;i++) 26 { 27 mina=0x3f3f3f3f; 28 minid=0; 29 for(j=1;j<=n;j++) 30 if(ok[j]&&!vis[j]&&mina>dis[j]) 31 { 32 mina=dis[j]; 33 minid=j; 34 } 35 sum+=mina; 36 dis[minid]=0; 37 vis[minid]=1; 38 for(j=1;j<=n;j++) 39 if(ok[j]&&!vis[j]&&dis[j]>b[minid][j]) 40 dis[j]=b[minid][j]; 41 } 42 for(i=1;i<=n;i++) 43 if(ok[i]) 44 s1+=a[i]; 45 double tt=(double)sum/s1; 46 if(tt<anss) 47 { 48 anss=tt; 49 memcpy(ok2,ok,sizeof(ok)); 50 } 51 } 52 void dfs(int minn) 53 { 54 if(num>=m) 55 { 56 prim(); 57 return; 58 } 59 for(int i=minn+1;i<=n;i++) 60 if(!ok[i]) 61 { 62 ok[i]=1; 63 num++; 64 dfs(i); 65 ok[i]=0; 66 num--; 67 } 68 } 69 int main() 70 { 71 int i,j; 72 scanf("%d%d",&n,&m); 73 while(n!=0&&m!=0) 74 { 75 vec.clear(); 76 anss=2147483646; 77 num=0; 78 for(i=1;i<=n;i++) 79 scanf("%d",&a[i]); 80 for(i=1;i<=n;i++) 81 for(j=1;j<=n;j++) 82 scanf("%d",&b[i][j]); 83 dfs(0); 84 for(i=1;i<=n;i++) 85 if(ok2[i]) 86 vec.push_back(i); 87 for(i=0;i<vec.size()-1;i++) 88 printf("%d ",vec[i]); 89 printf("%d ",vec[vec.size()-1]); 90 scanf("%d%d",&n,&m); 91 } 92 return 0; 93 }