题目链接:pku2531 代码一: dfs #include <iostream> #include <algorithm> #include <vector> using namespace std; vector <int> v1,v2; int n,ans,a[22][22]; void sum() { int temp=0; for(int i=0;i<v1.size();i++) for(int j=0;j<v2.size();j++) temp+=a[v1[i]][v2[j]]; if(temp>ans)ans=temp; } void dfs(int i) { if(i==n+1){ sum();return ;} v1.push_back(i); dfs(i+1); v1.pop_back(); v2.push_back(i); dfs(i+1); v2.pop_back(); } int main(int argc, char *argv[]) { while(cin>>n) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j]; ans=0; dfs(1); cout<<ans<<endl; } return 0; } 代码二:随机化算法 摘自 GOODNESS /*解法类型:随机化算法 题目大意: 把一个完全图分成两部分,使得连接这两部分边的权和最大。 解题思路: 随机改变一个点的位置,算出权和,重复200000次,取最大值输出。 提交情况: 1.Wrong Answer多次:随机的次数不够。 2. Time Limit Exceeded多次,由于每次都随机分配所有点的位置,所以随机次数稍多后就超时。 注意:这种方法用时较多,在poj上可以过,在zoj上过不了…… 此题还可以用动态规划或应用巧妙的剪枝来做,可是我没找到方法…… */ #include <iostream> using namespace std; int map[30][30],part[30];//part数组用来将点分开 int main() { long n,i,j,a; while(cin>>n) { for(i=1;i<=n;i++) for(j=1;j<=n;j++) cin>>map[i][j]; memset(part,0,sizeof(part)); long max=-1,t,sum=0; t=200000;//随机的次数 while(t--) { a=rand()%n+1;//随机产生一个数,并得到于之对应的点的位置 if(part[a]) part[a]=0;//改变这个点的位置 else part[a]=1; for(i=1;i<=n;i++)//更新改变后图的权和 { if(part[i]&&part[a]&&a!=i) sum-=map[a][i]; if(!part[i]&&!part[a]&&a!=i) sum-=map[a][i]; if(part[i]&&!part[a]) sum+=map[a][i]; if(!part[i]&&part[a]) sum+=map[a][i]; } if(sum>max) max=sum;//更新最大值 } cout<<max<<endl; } return 0; } 代码三:二进制+枚举 摘自 孤独_守候 #include<stdio.h> int g[25][25]; int flag[4005]; int main() { int n,i,j,t,s,k,f,ans; while(scanf("%d",&n)!=EOF) { t=1<<(n-1); for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&g[i][j]); ans=-1; for(i=0;i<t;i++) { s=i; f=0; for(j=0;j<n;j++)//枚举组合数 { flag[j]=s&1; s>>=1; } /* for(j=0;j<n;j++) printf("%d=%d ",j,flag[j]); printf("/n");*/ for(j=0;j<n;j++) { if(!flag[j])continue; for(k=0;k<n;k++) { if(flag[k])continue; f+=g[j][k]; } } if(ans<f)ans=f; } printf("%d/n",ans); } }