您的位置:首页 > 编程语言

【ZOJ3471】Most Powerful, 思路+源代码+解题报告(好久没写解题报告了……)【目标达成:0.1%】

2012-08-01 23:46 302 查看
/**

Problem:ZOJ3471-Most Powerful.
Reference:http://blog.csdn.net/magicnumber/article/details/6182891
Knowledge point:状态压缩DP
Thought:
根据炮兵阵地(那是别的题)和这道题,还有一次多校的经验(就是那个类似拼图的那个题,给你
几个块问你能拼多大的长方形),貌似状态数少的,就可以用状态压缩。
比如这道题,N <= 10,并且一个气体只有“用”和“没用”两种属性,那么就可以用二进制表示状态。
2^10可以用一个int存储。那么rp[i]中对应的i的二进制表示,就代表了一种状态。状态的转移就在
rp[i]和rp[j]之间进行。
(rp数组和dp数组表示的意思相同,后文不再赘述。由于本人靠人品进行动态规划,故起名如此)
状态转移方程为:
dp[i|cst[j]]=Max(dp[i|cst[j]],dp[i]+map[k][j]);
map[k][j]表示的是用j撞k获得的能量值。
唔,跟我第一次想的不一样。就是说,存在类似
0100000,0010000,00010000...(分别表示总共8个气体,用了第二个,第三个,第四个气体,用以举例子)
这种状态,我刚开始想的是直接就是01100000(就是直接两个气体对撞)……
【注意,我的想法是错误的,这是写给我自己看的,你们无视就好】
那么0100000代表的就是第二个气体已经用过了。
注意,跟谁撞了,这不重要。重要的是用掉了哪个气体。
————————————关于dp[i|csj[j]]=max(dp[i|cst[j]],dp[i]+map[k][j]);的证明如下——————————————
假设剩下最后两种气体
那么最优解一定是两种气体i,j中map[i][j],map[j][i]最大的。
而且,对于最优解来说,这时候(剩下两种气体的时候)已经获得的能量肯定是n-2种气体对撞获得能量最大的
符合最优子结构。
状态转移方程也是根据以上推出来的。
这个。。。只能意会啊,我真的证明不明白T^T,自己用样例看一下就知道了。

*/
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cstdio>
using namespace std;

const int MAX_SIZE = 15;
const int MAX_BINARY = 1024 + 1; // avoid overflow.
int power[MAX_SIZE][MAX_SIZE];
int dp[MAX_BINARY];
int bin[] = { 1,2,4,8,16,32,64,128,256,512,1024 } ;// 2^10 = 1024;
int solve(int N)
{
int maxV = 0;
for(int i = 0 ; i < bin
; i++) //expand every state.
{
for(int j = 0 ; j < N; j++)
{
if( ( i & bin[j] ) != 0 )
continue; //gas j has been used.
for(int k = 0 ; k < N ; k++)
{
if( ((i & bin[k])==0) && (k != j) )
{
dp[i | bin[j]] = max(dp[i | bin[j]],dp[i]+power[k][j]);
}
}
}
}
for(int i = 0 ; i < bin
; i++)
{
maxV = max(maxV,dp[i]);
}
return maxV;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("B:\\acm\\SummerVacation\\DP-II\\A.in","r",stdin);
freopen("B:\\acm\\SummerVacation\\DP-II\\A.out","w",stdout);
#endif
int N,res;
while(scanf("%d",&N) != EOF && N)
{
memset(dp,0,sizeof(dp));
for(int i = 0 ; i < N ; i++)
{
for(int j = 0 ; j < N ; j++)
{
scanf("%d",&power[i][j]);
}
}
res = solve(N);
printf("%d\n",res);
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐