ZOJ 3471 Most Powerful

题意:N个原子,两两碰撞会产生一定的能量,如果i去碰撞j,产生能量power[i][j],且j会消失。如果j去碰撞i,则会产生能量power[j][i],且i消失。问N个原子相互碰撞所能产生的最大能量。


分析:状态压缩DP。假设一个数,第i位表示第i个原子是否被灭掉,如果被灭掉则为1,没被灭掉为0,那么所有状态都可以用2^n范围内的数来表示。假设对于其中一个数(n=4)

1 0 1 0,(也就是十进制的10)则表示第二个原子和第四个原子都被灭掉,而第一、三个原子幸存,那么,假设知道这个状态下释放能量的最大值,那么我们可以拓展出1 1 1 0 和1 0 1 1 这两个状态通过1 0 1 0达到的值,那么对于每个状态进行这种拓展,那么就可以求出每个状态下释放能量的最大值,所以最后的最大值就求出来了。


Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;

const int inf=0x3f3f3f3f;
int power[15][15],dp[1<<10];
int n;

int main()
{
    while(scanf("%d",&n),n){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++)
                scanf("%d",&power[i][j]);
        }
        int ans=0;
        memset(dp,0,sizeof(dp));
        for(int s=0;s<(1<<n)-1;s++){
            for(int i=0;i<n;i++){
                if(s&(1<<i)) continue;
                for(int j=0;j<n;j++){
                    if(s&(1<<j)||j==i) continue;
                    dp[s|(1<<i)]=Max(dp[s]+power[j][i],dp[s|(1<<i)]);
                    ans=Max(ans,dp[s|(1<<i)]);
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(ZOJ 3471 Most Powerful)