标签:理解 format decided maximum string ... traffic div after
Input
Output
Sample Input
3 0 50 30 50 0 40 30 40 0
Sample Output
90
解题思路:
首先这个题目的题意就比较难理解。题目大意:有n个点,每两个点之间都有一段距离,现在要把这些点分为两部分,使得一个部分的点到另一个部分所有的点的距离和最大。(学过离散的就知道这是一个完全图)比如题中的例子:就是一个K3图(3个顶点的完全图,一个三角形),设顶点为A,B,C.由题意可知:A到B的距离为30,B到C为40,C到A为50.当把A放一边,B,C放一边时,总距离为:A到B的距离(30)+A到C的距离(50)=80.当把C放一边,A,B一边时,总距离为AC+BC=90,另一种为30+40=70.所以最大的距离和为90.
看懂题目的可能都知道要用枚举来找最大距离和,但是怎么枚举呢?用for循环?肯定行不通的。这里就用”二进制枚举“来枚举所有情况并找到最大值。
二进制枚举(非递归):
用数组的值为0或1来把所有的点来分为两部分。
1 int a[10002]; 2 memset(a,0,sizeof(a)); //清零。 3 for (int i=0;i<n;i++) //n:枚举的次数。 4 { 5 a[0]++; //第一位加一。 6 for (int j=0;j<n;j++) 7 if (a[j]==2) 8 { 9 a[j]=0; //当这一位等于2时,又清零 10 a[j+1]++; //并使下一位加一。 11 } 12 }
代码可能不好理解。下面模拟过程。
开始时的数组: 00000
a[0]++;后 10000
a[0]++等于2后,a[0]=0;a[0+1]++;01000
接下来是:
11000
00100
10100
01100
......
11111
这样就把所有的情况都枚举出来了。
下一步就只要把所有枚举中0或1的所有对应值求和,并找到最大值就可以了。
全部代码如下:
#include <iostream> #include <cstring> #include <cmath> using namespace std; int a[22][22],tab[22]; int main() { int n,i,j,k,ans=0,sum=0,z; cin >>n; for (i=1;i<=n;i++) for (j=1;j<=n;j++) cin >>a[i][j]; k=pow(2,n-1); //枚举的情况总数。 for (i=1;i<=k;i++) { tab[1]++; sum=0; for (j=1;j<=n;j++) if (tab[j]==2) { tab[j]=0; tab[j+1]++; } else break; for (j=1;j<=n;j++) { if (tab[j]==0)continue; //找到每一个为1的点。 for (z=1;z<=n;z++) if (tab[z]==0) //并把这个1到所有0的距离求和。 sum+=a[j][z]; } ans=max(ans,sum); //找到最大的的和。 } cout <<ans<<endl; return 0; }
标签:理解 format decided maximum string ... traffic div after
原文地址:http://www.cnblogs.com/shendeng23/p/7287186.html