您的位置:首页 > 其它

暑期个人赛--第六场--B(常复习~!!!)

2014-07-28 11:32 134 查看




445. 高兴

时间限制 4000 ms 内存限制 65536
KB


题目描述

小弱有n个玩具,现在小弱想把他们排列成一行,把玩具j放在玩具i的右边相邻的位置上,他将得到一个高兴值Hij.


输入格式

输入有多组数据。

每组数据以一个整数n(n <= 18)开头。

接下来n行, 每行n个整数。 第i行第j列Hij( Hij的绝对值 <= 10000)代表把玩具j放在玩具i的右边相邻的位置时高兴值。输入保证Hii = 0,最左边只考虑与右边相邻的玩具,最右边只考虑与左边相邻的玩具。


输出格式

对于每组数据输出最大高兴值。


输入样例

2
0 1
2 0
3
0 -1 7
3 0 3
3 3 0



输出样例

2
10




赛中提交:NULL
赛后AC:WA WA WA WA WA WA AC

题目大意:
hij代表将j号放在i号右边时所可以得到的收益,最左和最右只与其右其左有关(也就是受第一个被放置的收益为零,最后一个放置的收益由其左边的决定)
要求求出一个排序使得收益最大。

方法:
状态压缩DP

反省:
为什么比赛中没有想出来呢?
其实在比赛中还是想到了状压DP的,因为发现即使使用三个下标也无法准确表现状态
但是看到n最大是18,误以为这么大的n不能用状压,所以误认为是自己的DP水平不够
就没有用状压了

所以总的来说,就是自己对DP还不够熟悉,不够有信心;
自己对状压DP不够熟悉,不知道只要不超过20都可以用状压,而且不了解状压的模型

那么为什么赛后也没有很快AC呢- -首先不够自信是第一,总是担心DP过程出错,一直在检查
但是其实错误时因为收益是有可能出现负值的,但是res只初始化为0而不是-999999999...罪该万死啊啊~!!!

另外,为什么给这次加上常复习的标签呢?
(1)因为这题貌似是做DP这么久以来第一次自己有目的的更改DP式后自己AC的题目
以前比较缺乏自己检验递推式正确导出递推式的能力,看着循环也很难在脑中过出DP的过程
实际上这个过程是十分重要的,这次是第一次那么完整的做到了,以后也要注意加强
(2)还因为由于出自自己的手,这是一个十分适合自己使用的状压DP的模板

这里总结一下需要注意的地方,
(1)DP循环的起点和终点,这个时候要注意检查DP下标和收益函数的对应关系
(2)循环(坐标)的先后次序。这个需要自己在脑中将DP过程过一遍,弄清楚哪些数据是先计算出来用于后边计算的
有没有出现后效性失效,以及已经计算到后面,但是前面还没计算到的情况

下面是AC代码:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <functional>
#define maxn 20
#define INF -999999999

using namespace std;
int h[20][20]={0};
int dp[600000][20];

int main()
{
int n;
while(scanf("%d",&n)!=EOF){
int a,b,c;
for(int i=0;i<n;i+=1){
for(int j=0;j<n;j+=1){
scanf("%d",&a);
h[i][j]=a;
}
}

for(int s=0;s<1<<n;s+=1){
fill(dp[s],dp[s]+n,INF);
}

for(int i=0;i<n;i+=1){
dp[1<<i][i]=0;
}

for(int s=1;s<=(1<<n)-1;s+=1){
for(int i=0;i<n;i+=1){
if(!((s>>i)&1))
for(int j=0;j<n;j+=1){
if(((s>>j)&1)&&i!=j){
dp[s|(1<<i)][i]=max(dp[s|(1<<i)][i],dp[s][j]+h[j][i]);
//printf("(%d %d)  %d\n",i,j,dp[s|1<<i][i]);
}
}
}
}

int res=-999999999;
for(int i=0;i<n;i+=1){
res=max(dp[(1<<n)-1][i],res);

}
printf("%d\n",res);
}

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