题目大意: 宾馆有个伸缩门,其开放状态用[0,k]之间某个数来表示,每秒钟它至多可以伸长或减少1个单位。现在有n个强盗,他们会在ti的时间到达宾馆,如果此时门的开放度和他的身材si恰好相同,他就会进来,并得到pi的加分。一开始门是关闭的(开放度为0),请你求出时刻t的最大加分。
解题思路:1)这道题的状态很容易就可以找出来:dp[i][j]表示在第i秒钟门的宽度为j所取得的最大加分。
2)那么转移就是:dp[i][j]=Max{dp[i-1][j+1],dp[i-1][j-1],dp[i][j]}+dp[i][j]~前一个时刻可以由三个状态转变而来,直接求最大值就可以了
3) 这道题的空间限制是10000K~,完整的数组开不了,只能开滚动数组~(WA了之后才发现的)
~~本以为改为滚动数组后就过了~~,没想到果断T了~~,没办法,又加了张hash记录强盗在什么时刻到达宾馆来稍微稍微降低复杂度。
代码:
1
#include <iostream>
2
#include <cstdio>
3
#include <cstring>
4
#include <string>
5
#include <cmath>
6
#include <algorithm>
7
8
using namespace std;
9
10
struct Person
11

{
12
int t,s,p;
13
}num[110];
14
int dp[3][110];
15
int hash[30100];
16
int n,t,k,summ;
17
18
19
void init()
20

{
21
memset(dp,0,sizeof(dp));
22
memset(hash,0,sizeof(hash));
23
}
24
25
void get_DP()
26

{
27
for (int i=0; i<=t; i++)
28
{
29
for (int j=0; j<=k && j<=i; j++)
30
{
31
summ=0;
32
if (hash[i]!=0)
33
{
34
for (int l=0; l<n; l++)
35
if (i==num[l].t && j==num[l].s) summ+=num[l].p;
36
}
37
if (j==k) dp[i%3][j]=max(dp[(i+2)%3][j-1],dp[(i+2)%3][j]);
38
else if (j==0) dp[i%3][j]=max(dp[(i+2)%3][j+1],dp[(i+2)%3][j]);
39
else dp[i%3][j]=max(max(dp[(i+2)%3][j-1],dp[(i+2)%3][j]),dp[(i+2)%3][j+1]);
40
dp[i%3][j]+=summ;
41
}
42
}
43
}
44
45
int cmp(const Person &a,const Person &b)
46

{
47
if (a.t==b.t) return a.s<b.s; else return a.t<b.t;
48
}
49
50
int main()
51

{
52
scanf("%d%d%d",&n,&k,&t);
53
54
for (int i=0; i<n; i++)
55
scanf("%d",&(num[i].t));
56
for (int i=0; i<n; i++)
57
scanf("%d",&(num[i].p));
58
for (int i=0; i<n; i++)
59
scanf("%d",&(num[i].s));
60
sort(num,num+n,cmp);
61
init();
62
for (int i=0; i<n; i++)
63
hash[num[i].t]=1;
64
get_DP();
65
int maxx=-1;
66
for (int i=0; i<=k; i++)
67
if (maxx<dp[t%3][i]) maxx=dp[t%3][i];
68
printf("%d",maxx);
69
return 0;
70
}
71