题意:N个歹徒去一个餐馆,旅馆门有k个打开程度(每个打开程度为门的一个状态),每个歹徒拥有自己的肥胖度(两个歹徒的肥胖度可能相同)和繁荣度(prosperity),歹徒在i 时刻到餐厅来(两个歹徒可能同时来餐馆),若此时刻门的打开程度与歹徒的肥胖度相同,则歹徒就进入餐馆,同时餐馆获得这个歹徒相应的繁荣度,若歹徒到来时门的打开程度与歹徒的肥胖程度不同,则歹徒离开且不再回来。门的打开程度在每个单位时间里改变一个单位的打开程度,可以保持当前的打开程度不变,也可以关闭或打开一个单位程度。
要求:你来控制门的打开程度,使餐馆最后获得最大的繁荣度。 最初门的打开程度为0(门关着的)。
dp[ i ][ j ]表示第 i 个时刻门的打开程度为 j 时获得的最大的繁荣度。
状态转移方程:dp[ i ][ j ] = MAX(dp[ i - 1 ][ j ], dp[ i - 1 ][ j + 1 ], dp[ i - 1 ][ j + 1 ]) + w; w为此状态下能够获得的繁荣值。
注意处理 j == 0 和 j == k 的情况。
#include <iostream>
#include <algorithm>
using namespace std;
#define N 102
#define T 30002
int dp[2][N];
bool mark[T];
struct Gangster
{
int tt, p, s;
} g[N];
inline int MAX(int a, int b)
{
return a>b?a:b;
}
int main()
{
int n, k, t;
int i, j, p;
memset(mark, false, sizeof(mark));
scanf("%d %d %d", &n, &k, &t);
for(i = 1; i <= n; i++){
scanf("%d", &g[i].tt);
mark[g[i].tt] = true;
}
for(i = 1; i <= n; i++)
scanf("%d", &g[i].p);
for(i = 1; i <= n; i++)
scanf("%d", &g[i].s);
bool flag = false;
int w;
memset(dp, 0, sizeof(dp));
for(i = 0; i <= t; i++){
for(j = 0; j <= i && j <= k; j++){
w = 0;
if(mark[i])
{
for(p = 1; p <= n; p++)
if(g[p].s == j && g[p].tt == i)
w += g[p].p;
}
if(j == 0) dp[i%2][j] = MAX(dp[1-i%2][j], dp[1-i%2][j+1]);
else if(j == k) dp[i%2][j] = MAX(dp[1-i%2][j], dp[1-i%2][j-1]);
else dp[i%2][j] = MAX(MAX(dp[1-i%2][j], dp[1-i%2][j-1]), dp[1-i%2][j+1]);
dp[i%2][j] += w;
}
}
int ans = 0;
for(i = 0; i <= k; i++)
if(ans < dp[t%2][i])
ans = dp[t%2][i];
printf("%d\n", ans);
//system("pause");
return 0;
}