POJ 2531 Network Saboteur(DFS+枝切り)
1248 ワード
タイトルリンク:http://poj.org/problem?id=2531
n個の点があって、任意の2点の間の重み値を与えて、今点をそれぞれA集合あるいはB集合に入れて、2つの集合の重み値の和の最大値を求めます.
直接暴力は過去にも問題なく、110 ms、47 msまで枝を切った.
最初はすべての集合がAにあると考えられ,次に列挙して点をBに加える.
具体的な説明はコードを参照してください.
n個の点があって、任意の2点の間の重み値を与えて、今点をそれぞれA集合あるいはB集合に入れて、2つの集合の重み値の和の最大値を求めます.
直接暴力は過去にも問題なく、110 ms、47 msまで枝を切った.
最初はすべての集合がAにあると考えられ,次に列挙して点をBに加える.
具体的な説明はコードを参照してください.
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-6;
const int INF=0x3f3f3f3f;
const int maxn=25;
int n,c[maxn][maxn];
int set[maxn];
int ans;
void dfs(int id,int sum){
set[id]=1;// id B
int tmp=sum;
for(int i=1;i<=n;i++){
if(set[i]==0) tmp+=c[i][id];// id
else tmp-=c[i][id];// id
}
if(tmp>ans) ans=tmp;
for(int i=id+1;i<=n;i++){
if(tmp>sum){// , ,
dfs(i,tmp);
set[i]=0;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&c[i][j]);
memset(set,0,sizeof(set));// A
ans=0;
dfs(1,0);//
printf("%d
",ans);
}
return 0;
}