标签:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 9544 | Accepted: 4542 |
Description
Input
Output
Sample Input
3 0 50 30 50 0 40 30 40 0
Sample Output
90
题意:给出n个点(0-n-1),接下来n行,每行有n个数,第i行代表第i-1个数距离n个点的距离,问将这些点分为两部分,两个点集之间的权值最大值为多少。例如样例中讲0,1,2分为两部分(1,3)和(2)两部分,则最长距离为map[1][2]+map[3][2]=90。
思路:怎么想都没看出这题和dfs有什么关系,知道看了巨巨的题解,恍然大悟,涨姿势了。首先我们将所有的店标记为0(即所有点放在一个集合里),然后取出一个site标记为1(即将该点放在另一个集合里),这是对于和site在一个集合里的点,我们减去他们两个之间的权值,对于不在一个集合里的点,我们加上他们之间的权值。最后的结果为最大值。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> #include <set> #include <queue> #include <stack> using namespace std; const int inf=0x3f3f3f3f; int map[40][40]; int g[40]; int n,res; void dfs(int site,int sum) { int i; g[site]=1;//取出点 int num=sum; for(i=0;i<n;i++){ if(g[i]==1)//与site在一个集合里的点 num-=map[site][i];//减去他们之间的权值 else//否则和site不在一个集合里 num+=map[site][i];//加上他们之间的权值 } res=max(res,num);//依次循环结束找到的最大值 for(i=site+1;i<n;i++){//然后遍历剩下的点 if(num>sum){//小剪枝,如果加入了点site后两个集合之间的权值小了,则就不需要遍历这个点。 dfs(i,num); g[i]=0; } } } int main() { int i,j; while(~scanf("%d",&n)){ memset(map,0,sizeof(map)); memset(g,0,sizeof(g)); for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&map[i][j]); res=-inf; dfs(0,0); printf("%d\n",res); } return 0; }
POJ 2531-Network Saboteur(dfs+剪枝)
标签:
原文地址:http://blog.csdn.net/u013486414/article/details/43890357