ZOJ 3471(状态压缩DP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ 3471(状态压缩DP)相关的知识,希望对你有一定的参考价值。

题意:有n个原子,每当两个原子碰撞时就会产生能量,并且消耗其中一个原子。已知每两个原子碰撞时消耗其中指定一个原子所产生的能量,问最多能产生多少能量?

状态表示 dp[state] 状态为state时的最大能量

转移方程  dp[state] = max(dp[state],dp[state‘]+a[i][j])

边界条件  dp[i] = 0

#include <algorithm>
#include <cstdio>
#include <cstring>

#define Max 1000001
#define MAXN 11
#define MOD 100000000
#define rin freopen("in.txt","r",stdin)
#define rout freopen("1.out","w",stdout)
#define Del(a,b) memset(a,b,sizeof(a))
#define INF 0x1f1f1f1f
using namespace std;
typedef long long LL;
const int MAXNUM=(1<<MAXN);
int n;
int a[MAXN][MAXN];
int dp[MAXNUM];
int main() {
    //rin;
    while(scanf("%d",&n)!=EOF){
        if(n==0)
            break;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
            }
        }
        Del(dp,0);
        int full=1<<n;
        for(int s=0;s<full;s++){
            for(int i=0;i<n;i++){
                if((s&(1<<i)))continue;
                for(int j=0;j<n;j++){
                    if(i==j)continue;
                    if((s&(1<<j)))continue;
                    int newS=(s|(1<<j));//从s状态中删去有气体j的状态
                    dp[newS]=max(dp[newS],dp[s]+a[i+1][j+1]);
                }
            }
        }
        int ans=0;
        for(int s=0;s<full;s++)
            ans=max(ans,dp[s]);
        printf("%d\n",ans);
    }
    return 0;
}

根据s由大到小还是由小到大,转移方程不同。

  for(int i=(1<<n)-1;i>=0;i--)  
     for(int j=0;j<n;j++)  
     {  
         if(i&(1<<j))  
         {  
           for(int k=0;k<n;k++)  
           {  
              if(k==j)continue;  
              if(i&(1<<k))continue;  
              dp[i]=max(dp[i],dp[i|(1<<k)]+a[j][k]);  
            }  
          }  
     } 

 

以上是关于ZOJ 3471(状态压缩DP)的主要内容,如果未能解决你的问题,请参考以下文章

zoj 3471 状压DP

ZOJ 3471 Most Powerful(状压DP)

zoj 3471 Most Powerful 状压dp

zoj 3471 Most Powerful (有向图)最大生成树 状压dp

ZOJ-3777 Problem Arrangement(状态压缩DP)

zoj 1100 - Mondriaan&#39;s Dream