题面:
思路:
暴力搜索选在A队的队员(假设分为A,B两队)。
在暴力选择队员的时候,无法确定后面的选择,所以无法确定那个值要添加,
多阶段决策,想到DP,但是大可不必
正难则反,将已知在一队的队员的竞争值从该名队员(dfs正在选择的队员)的竞争总和减去,
且是减去2倍,因为在前面选择队员时,没有考虑到这个队员,所以竞争值要减两次,
这个减去两倍的操作,也解决了后面对前面选择的影响。
AC code:
#include<bits/stdc++.h>
// #include<iostream>
// #include<cstdio>
// #include<vector>
// #include<cstring>
using namespace std;
#define per(i,a,b) for(int i = (a);i <= (b);++i)
#define rep(i,a,b) for(int i = (a);i >= (b);--i)
const int maxn = 14*2 + 10;
typedef long long LL;
#define INF 1e18
int n = 0,m = 0;
LL v[maxn][maxn],h[maxn];
vector<int> g;//存储
LL ans = 0;
/*
在暴力选择队员的时候,无法确定后面的选择,所以无法确定那个值要添加,
多阶段决策,想到DP,但是大可不必
正难则反,将已知在一队的队员的竞争值从该名队员(dfs正在选择的队员)的竞争总和减去,
且是减去2倍,因为在前面选择队员时,没有考虑到这个队员,所以竞争值要减两次,
这个减去两倍的操作,也解决了后面对前面选择的影响。
*/
void dfs(int depth,LL sum){
if(g.size() == n){
ans = max(ans,sum);
return ;
}
if(depth > 2*n){
return ;
}
if(g.size() + 2*n - depth + 1 < n){//可行性剪枝
return ;
}
int si = g.size();
LL curr = h[depth];
per(i,0,si-1){
curr -= 2*v[depth][g[i]];//减去前面已经选了的队员的竞争值
//由于在前面选择队员时,没有考虑到这个队员,所以竞争值要减两次
}
g.push_back(depth);//选该号队员
dfs(depth+1,sum + curr);
g.pop_back();//不选该号队员
dfs(depth+1,sum);
}
int main(){
while(~scanf("%d",&n)){
// init();
per(i,1,2*n){
per(j,1,2*n){
scanf("%lld",&v[i][j]);
h[i] += v[i][j];
}
}
dfs(1,0);
printf("%lld\n",ans);
}
return 0;
}