NBUT 动态规划专题——A - Gangsters

Description

N gangsters are going to a restaurant. The i-th gangster comes at the time Ti and has the prosperity Pi. The door of the restaurant has K+1 states of openness expressed by the integers in the range [0, K]. The state of openness can change by one in one unit of time; i.e. it either opens by one, closes by one or remains the same. At the initial moment of time the door is closed (state 0). The i-th gangster enters the restaurant only if the door is opened specially for him, i.e. when the state of openness coincides with his stoutness Si. If at the moment of time when the gangster comes to the restaurant the state of openness is not equal to his stoutness, then the gangster goes away and never returns. 
The restaurant works in the interval of time [0, T]. 
The goal is to gather the gangsters with the maximal total prosperity in the restaurant by opening and closing the door appropriately. 

Input

?The first line of the input file contains the values N, K, and T, separated by spaces. (1 <= N <= 100 ,1 <= K <= 100 ,0 <= T <= 30000 ) 
?The second line of the input file contains the moments of time when gangsters come to the restaurant T1, T2, ..., TN, separated by spaces. ( 0 <= Ti <= T for i = 1, 2, ..., N) 
?The third line of the input file contains the values of the prosperity of gangsters P1, P2, ..., PN, separated by spaces. ( 0 <= Pi <= 300 for i = 1, 2, ..., N) 
?The forth line of the input file contains the values of the stoutness of gangsters S1, S2, ..., SN, separated by spaces. ( 1 <= Si <= K for i = 1, 2, ..., N) 
All values in the input file are integers. 

Output

Print to the output file the single integer ?the maximal sum of prosperity of gangsters in the restaurant. In case when no gangster can enter the restaurant the output should be 0.

Sample Input

4 10 20
10 16 8 16
10 11 15 1
10 7 1 8

果然dp很难,一般做法是,设dp[i][j]表示时间在0-i,门的状态为j时的最优解,那么

dp[i][j]=max(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])

想要求最优解,那么当然从第i时间可能能进入的情况入手,那么上一个时间的门的状态显然只有3个,由于第i时间的最优解只和第i-1时间有关,本题内存也有限制,所以要采用滚动数组,下面是代码


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<iostream>
#include<set>
#include<vector>
using namespace std;

int dp[2][105];

struct node
{
int p,s,t;
}people[105];

int _hash[30010][100];
int main()
{
int n,k,t;
while(~scanf("%d%d%d",&n,&k,&t))
{
memset(_hash,0,sizeof(_hash));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%d",&people[i].t);
for(int i=1;i<=n;i++)
scanf("%d",&people[i].p);
for(int i=1;i<=n;i++)
scanf("%d",&people[i].s);
for(int i=1;i<=n;i++)
if(people[i].s <= people[i].t)
_hash[ people[i].t][people[i].s + 1]+=people[i].p;//我们把可以进入的人全部保存在hash数组里,计算出每个时间点可以进入的人的价值总和
for(int i=1;i<=t;i++)
for(int j=1;j<=k+1 && j<=i+1;j++)
dp[i&1][j]=max(dp[(i-1)&1][j-1],max(dp[(i-1)&1][j],dp[(i-1)&1][j+1]))+_hash[i][j];
int ans=0;
for(int i=1;i<=k+1;i++)
ans=max(ans,dp[t&1][i]);
printf("%d\n",ans);
}
return 0;
}

遗憾的是,按上面的写法,我还是超内存了,也许可以在此基础上优化,但是,从递推式本身出发,可以大大解决内存的问题。按第i个人来考虑,如果第i个人可以进入,那么就先把dp[i]赋值为value[i],显然第i个人的状态一定要继承到前i个人中最优的那个人(当然那个人也要可以进入那扇门)

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;

int dp[110];

struct node
{
int p,s,t;
}gaster[105];

int _ok[105];

int cmp(node a,node b)
{
return a.t < b.t;
}

int main()
{
int n,t,k;
while(~scanf("%d%d%d",&n,&k,&t))
{
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
scanf("%d",&gaster[i].t);
for(int i=0;i<n;i++)
scanf("%d",&gaster[i].p);
for(int i=0;i<n;i++)
scanf("%d",&gaster[i].s);
sort(gaster,gaster+n,cmp);
for(int i=0;i<n;i++)
if(gaster[i].s <= gaster[i].t)
_ok[i]=gaster[i].p;
else
_ok[i]=0;
for(int i=0;i<n;i++)
{
if(_ok[i]!=0)
dp[i]=_ok[i];
else
dp[i]=0;
for(int j=0;j<i;j++)
if(dp[j] && fabs(gaster[i].s - gaster[j].s) <= fabs(gaster[i].t - gaster[j].t ))//设//一段时间内门的变化值为Δt,那么当且仅当s的变化值Δs <=Δt才满足第i个人可以进入门的条件
dp[i]=max(dp[i],dp[j]+_ok[i]);
}
int ans=0;
for(int i=0;i<n;i++)
ans=max(ans,dp[i]);
printf("%d\n",ans);
}
return 0;
}


你可能感兴趣的:(NBUT 动态规划专题——A - Gangsters)