题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4257
题目大意:
有n个原子,当两个原子相撞的时候,其中一个原子会死掉并且释放出相应的能量。求取这n个原子进行碰撞能释放的最大能量。(n<=10)
解题思路:
因为n的个数比较小,所以这个题目可以使用装药压缩DP。
状态转移方程为:
dp[i]=max(dp[i],dp[i]+Map[j][k])
dp[i]表示状态为i的时候最大的释放能量,Map[j][k]表示j和k碰撞的时候k死掉的时候释放的能量。
源代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int Map[11][11]; //表示第i个原子与第j个原子相撞,第j个原子死掉释放的能量
int dp[(1<<11)]; //表示状态i下,最后死掉的原子是j
int s[11]={1,2,4,8,16,32,64,128,256,512,1024}; //表示原子个数为n的时候的最大状态数目
int n;
void DP() //最后还剩下一个原子没有死掉
{
int i,j,k,t,l,Max=0,temp;
for(i=0;i<s[n];i++) //枚举每种状态
{
//只要k和t没死,并且k不等于t,那么就可以发生碰撞
for(k=0;k<n;k++) //枚举下一次进行碰撞的原子
{
for(t=k+1;t<n;t++) //枚举下一次进行碰撞的原子
{
if((i&(1<<t))==0 && (i&(1<<k))==0)
{
l=i+s[t]; //t消失
dp[l]=max(dp[l],dp[i]+Map[k][t]);
l=i+s[k]; //k消失
dp[l]=max(dp[l],dp[i]+Map[t][k]);
}
}
}
}
for(i=0;i<s[n];i++)
{
if(dp[i]>Max) Max=dp[i];
}
printf("%d\n",Max);
return;
}
int main()
{
//freopen("in.txt","r",stdin);
int i,j,k,t;
while(scanf("%d",&n)==1 && n)
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&Map[i][j]);
}
}
memset(dp,0,sizeof(dp));
DP();
}
return 0;
}