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 Most Powerful (有向图)最大生成树 状压dp