ZOJ 3471 Most Powerful (状压DP)

来源:互联网 发布:成都 都江堰旅游 知乎 编辑:程序博客网 时间:2024/05/17 11:07

n(<=10)种气体,两两相互碰撞会使得其中一种气体消失,同时释放出能量。问最多能释放出多少能量。
用一个2进制位表示气体是否存在,n种气体对应n位2进制位,表示一个状态。
设dp[i]表示在状态i下释放出的最大能量。
状态转移方程:

dp[i]=max(dp[i],dp[i]+a[k][j])
其中a[k][j]为气体k碰撞气体j,气体j消失后释放的能量。i’为上一种状态。

初始化:dp全部为0,从状态2^n-1开始枚举。

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define maxn 11#define inf 0x3f3f3f3fint D[maxn][maxn];int dp[1<<10];int main(){    int n,i,j,k;    while(~scanf("%d",&n)&&n)    {        for(i=1;i<=n;++i)            for(j=1;j<=n;++j) scanf("%d",&D[i][j]);        memset(dp,0,sizeof(dp));        for(i=(1<<n)-1;i>=3;--i)        {            for(j=1;j<=n;++j)            {                if(i&(1<<(j-1)))                {                    for(k=1;k<=n;++k)                    {                        if(j==k) continue;                        if(i&(1<<(k-1)))                        {                           dp[i^(1<<(k-1))]=max(dp[i^(1<<(k-1))],dp[i]+D[j][k]);                           dp[i^(1<<(j-1))]=max(dp[i^(1<<(j-1))],dp[i]+D[k][j]);                        }                    }                }            }        }        int ans=-1;        for(i=1;i<(1<<n);i<<=1)            ans=max(ans,dp[i]);        printf("%d\n",ans);    }    return 0;}
0 0