这是一道集合上的动态规划,和最优配对问题很相似,不同的是:最优配对问题的思想是配对后两个元素都消失,而合并游戏的思想是合理配对后只消失一个元素。那么合并到最后的时候肯定会有一个石子留下,但是并不确定会是哪个石子留下,所以需要对石子进行逐个枚举。
用数组d[S]来表示S集合中所能得到的最多硬币数目,用数组a[j][i]来表示石子j和i合并后所得的金币数目(合并后消失的是i),对第i个石子逐个进行枚举,即就是,假设第i个石子先消失,那么状态转移方程便是:d[S]=max(d[S],a[j][i]+d[S-{i}]).
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
#define Max 11
using namespace std;
int n,a[Max][Max],S,dp[1<<Max];
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
for(S=0;S<(1<<n);S++)
{
dp[S]=0;
for(i=0;i<n;i++)//对集合S中的元素逐个进行枚举
if(S&(1<<i)){
//printf("i=%d\n",i);
for(j=0;j<n;j++)
if(i!=j&&(S&(1<<j))){
//printf("j=%d\n",j);
dp[S]=max(dp[S],a[j][i]+dp[S^(1<<i)]);}
}
//printf("%d %d\n",S,dp[S]);
}
//printf("\n\n");
printf("%d\n",dp[(1<<n)-1]);
}
system("pause");
return 0;
}