poj1036 Gangsters

题意: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;
}


 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值