您的位置:首页 > 其它

ZOJ 3471 Most Powerful (状压DP,经典)

2015-10-08 09:56 232 查看
题意:

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

思路:

  一开始以为是找一个有序序列,使得能量最大,但是一个原子可能一直和别的原子碰撞且留到最后,所以序列是不行的。

  我们只需要知道消耗的是谁就行了,而不需要管到底是谁碰撞到这个被消耗的原子,那么状态转移就更方便了,每次找到两个还没有碰撞的,碰掉其中1个,然后转移。

//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <deque>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
using namespace std;
const double PI  = acos(-1.0);
const int N=11;
int g

, dp[1<<10];

int cal(int n)
{
memset(dp,0,sizeof(dp));
dp[0]=0;
for(int s=0; s<(1<<n); s++)
{
for(int i=1; i<=n; i++)
{
if( s&(1<<i-1) )   continue;
for(int j=1; j<=n; j++) //炸掉j
{
if(i==j)    continue;
if( s&(1<<j-1) )   continue;
dp[s|(1<<j-1)]=max(dp[s|(1<<j-1)],dp[s]+g[i][j] );
}
}
}
int ans=-10086;
for(int i=1; i<(1<<n); i++)
ans=max(ans, dp[i]);
return ans;
}

int main()
{
//freopen("input.txt","r",stdin);
int n;
while(scanf("%d",&n),n)
{
memset(g,0,sizeof(g));
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&g[i][j]);
printf("%d\n",cal(n));
}
return 0;
}


AC代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: