题意:两个原子如果碰撞会释放出相应的能量,并且其中有一个原子碰撞后会湮灭。
求所有碰撞状态中释放出的能量的最大值。
分析:由于最多只有10个原子,所以可以用二进制枚举所有状态,二进制位上为1表示
该原子已经湮灭。0表示还没有。
dp方程: dp[i]表示i状态下得到的最大能量。
dp[i|tmp]=max(dp[i|tmp],dp[i]+mp[k][j]);
dp[i]+mp[k][j]表示 第j个原子和第k个原子碰撞,第j个原子湮灭产生的能量。
tmp是由i上转移过来的,tmp=i|(1<<j)。
#include<cstdio> #include<iostream> #include<cstring> #define maxn (1<<10) using namespace std; int dp[maxn],mp[15][15]; int maxx(int x,int y) { return x>y?x:y; } int main() { int n,tot,tmp,ans; while(scanf("%d",&n)!=EOF) { if(n==0) break; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { scanf("%d",&mp[i][j]); } } memset(dp,0,sizeof(dp)); tot=(1<<10); for(int i=0;i<tot;i++) { for(int j=0;j<n;j++) { int tmp1=(1<<j); if((i&tmp1)==0) { for(int k=0;k<n;k++) { int tmp2=(1<<k); if((i&tmp2)==0 && j!=k) dp[i|tmp1]=maxx(dp[i|tmp1],dp[i]+mp[k][j]); } } } } ans=0; for(int i=0;i<tot;i++) { if(dp[i]>ans) ans=dp[i]; } printf("%d\n",ans); } return 0; }
也可以用个数组把所有状态存起来方便用。
即把10个位置每个原子湮灭的状态表示在数组state中。
#include<cstdio> #include<iostream> #include<cstring> #define maxn (1<<10)+10 using namespace std; int dp[maxn],mp[15][15]; int state[11]={1,2,4,8,16,32,64,128,256,512,1024}; int maxx(int x,int y) { return x>y?x:y; } int main() { int n,tot,ans; while(scanf("%d",&n)!=EOF) { if(n==0) break; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { scanf("%d",&mp[i][j]); } } memset(dp,0,sizeof(dp)); for(int i=0;i<state[n];i++) { for(int j=0;j<n;j++) //枚举每一个原子 { if((i&state[j])==0) //如果这个原子还没被湮灭 { for(int k=0;k<n;k++) //则找另一个还没湮灭的原子于j原子碰撞 { //使j原子湮灭 if((i&state[k])==0 && j!=k) dp[i|state[j]]=maxx(dp[i|state[j]],dp[i]+mp[k][j]); } } } } ans=0; for(int i=0;i<state[n];i++) { if(dp[i]>ans) ans=dp[i]; } printf("%d\n",ans); } return 0; }