您的位置:首页 > 其它

[hdu4940]Tourism Planning 状态压缩DP

2016-11-21 23:23 295 查看

题目描述

Several friends are planning to take tourism during the next holiday. They have selected some places to visit. They have decided which place to start their tourism and in which order to visit these places. However, anyone can leave halfway during the tourism and will never back to the tourism again if he or she is not interested in the following places. And anyone can choose not to attend the tourism if he or she is not interested in any of the places.

Each place they visited will cost every person certain amount of money. And each person has a positive value for each place, representing his or her interest in this place. To make things more complicated, if two friends visited a place together, they will get a non negative bonus because they enjoyed each other’s companion. If more than two friends visited a place together, the total bonus will be the sum of each pair of friends’ bonuses.

Your task is to decide which people should take the tourism and when each of them should leave so that the sum of the interest plus the sum of the bonuses minus the total costs is the largest. If you can’t find a plan that have a result larger than 0, just tell them to STAY HOME.

算法思路

其实状态压缩的想法是很简单的,因为奖励值需要我们知道在具体的状态之下到底存在哪些人,所以我们定义dp[i][j]为人员状态为j的时候到达i地点所可以得到的最优值.在每一步当中,都会离开一些人,人数未知,但是离开的人不会再回来,所以,我们得到的动态规划状态转移方程如下所示:

DP[i][j]=max(DP[i][t]+w),for every t that t&k=k

2.但是,这里要注意初始化的问题,我们在进行初始化的时候要将值定义为无穷小,只有这样才不会失去后效性,因为在上一步算出来的最优值是存在可能是一个负数的。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

#define MAXN 2050

const int INF = 1<<30;
int dp[11][MAXN];
int n,m;
int bonus[11][11];
int cost[11],interest[11][11];
int sumbonus[MAXN];
int sumpeople[MAXN];
int suminterest[11][MAXN];

void Solve()
{
int i,j,k,t;
int ans = 0;

memset(sumbonus,0,sizeof(sumbonus));
memset(sumpeople,0,sizeof(sumpeople));
memset(suminterest,0,sizeof(suminterest));
memset(dp,0,sizeof(dp));

for(i=0;i<(1<<n);i++)
dp[0][i] = -INF;

for(i=0;i<(1<<n);i++){
for(j=0;j<n;j++){
if(i&(1<<j)){
sumpeople[i]++;
for(k=j+1;k<n;k++){
if(i&(1<<k))
sumbonus[i] += bonus[j][k];
}
}
}
}

for(i=0;i<m;i++){
for(j=0;j<(1<<n);j++){
for(k=0;k<n;k++){
if(j&(1<<k))
suminterest[i][j] += interest[k][i];
}
}
}

for(i=0;i<(1<<n);i++){
dp[0][i] = suminterest[0][i]+sumbonus[i]-sumpeople[i]*cost[0];
}

for(i=1;i<m;i++){
for(k=0;k<(1<<n);k++){
dp[i][k] = dp[i-1][k];
for(t=0;t<(1<<n);t++){
if((t&k)==k && dp[i-1][k]>-INF)
dp[i][k] = max(dp[i][k],dp[i-1][t]+sumbonus[k]-sumpeople[k]*cost[i]+suminterest[i][k]);
}
}
}

for(i=0;i<(1<<n);i++)
ans = max(ans,dp[m-1][i]);

if(ans>0)printf("%d\n",ans);
else printf("STAY HOME\n");
return;
}

int main()
{
freopen("input","r",stdin);
int i,j;

while(1){
scanf("%d%d",&n,&m);
if(!n&&!m)break;

for(i=0;i<m;i++)
scanf("%d",&cost[i]);

for(i=0;i<n;i++){
for(j=0;j<m;j++)
scanf("%d",&interest[i][j]);
}

for(i=0;i<n;i++){
for(j=0;j<n;j++)
scanf("%d",&bonus[i][j]);
}

Solve();
}

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