http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109
给定m个人比赛,输了淘汰,赢了继续比,最后有一个人是冠军,给定一个数组,a[i][j]为 i战胜j的欢乐度,问你如何欢乐度最多。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n;
int a[15][15];
int dp[(1<<15)];
/* dp[i][j] i为还没有输的人的状态,如果输了,就是0,否则是1
j为当前的冠军。,把j这一维去掉也行,我就去掉了。
我们可以根据状态,不断枚举和当前胜者决战的人。(枚举和当前胜者决战的人时,一定有更多的人还没有输,
这个状态在之前肯定已经记录过了。)
*/
int main()
{ while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
memset(dp,0,sizeof(dp));
int all=(1<<n)-1;
for(int i=all;i>=0;i--){
for(int v=1;v<=n;v++){
if(i&(1<<(v-1))){
for(int p=1;p<=n;p++){
if(!(i&(1<<(p-1)))&&p!=v){
for(int x=1;x<=n;x++){
dp[i]=max(dp[i],dp[i|1<<(p-1)]+a[v][p]);
}
}
}
}}
}
//这个是描述的 i个人已经输了,
int ans=-1;
for(int i=1;i<=n;i++){
ans=max(ans,dp[1<<(i-1)]);
}
printf("%d\n",ans);
}
return 0;
}