POJ 1036 Gansters (DP)
题意:有个伸缩门,门的宽度0~K,每个时间可以伸长或缩短1个单位,有N个流氓,他们在T时刻到达,如果这时门的宽度正好与他们的stoutness相等时,便可获得一定的收入,问最大的收入是多少。
思路:典型的动态规划,用dp[t][k]来记录t时刻门宽度为k时的最大收入,由于这个值只与dp[t-1][]有关,所以可用滚动数组来实现,不然会超内存,另外存储流氓时还是利用struct来存放,否则内存不够,还有就是初始化的问题了:在t时刻(t<k)门的宽度是不可能大于t的,需要注意。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <bitset>
#include <vector>
using namespace std;
const int BORDER = (1<<26)-1;
const int MAXSIZE = 37;
const int MAXN = 110;
const int INF = 0x6ffffff;
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) x=((x+1)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) (x>0?x:-x)
typedef struct{
int stout,pros;
int next;
}Edge;
Edge edge[MAXN];
int pros[MAXN],dp[2][30005],come[MAXN],stout[MAXN];
int net[30005];
int con,N,T,K,index;
void add_edge(const int& u,const int& st,const int& pr)
{
edge[index].stout = st;
edge[index].pros = pr;
edge[index].next = net[u];
net[u] = index;
++index;
}
int get_pros(const int& tim,const int& stout)
{
int sum = 0;
for(int i = net[tim]; i != -1; i = edge[i].next)
if(edge[i].stout == stout)
sum += edge[i].pros;
return sum;
}
int init()
{
con = 0;
index = 0;
CLR(net,-1);
CLR(dp,0);
return 0;
}
int input()
{
int i,j,tmp;
for(i = 0; i < N; ++i)
IN(come[i]);
for(i = 0; i < N; ++i)
IN(pros[i]);
for(i = 0; i < N; ++i)
IN(stout[i]);
for(i = 0; i < N; ++i)
add_edge(come[i],stout[i],pros[i]);
return 0;
}
int _dp()
{
int i,j,tmp,n_door;
for(i = 1; i <= T; ++i)
{
n_door = MIN(i,K);
dp[con][0] = MAX(dp[1-con][0],dp[1-con][1]);
dp[con][n_door] = MAX(dp[1-con][n_door],dp[1-con][n_door-1]);
dp[con][n_door] += get_pros(i,n_door);;
for(j = 1; j < n_door; ++j)
{
tmp = MAX(dp[1-con][j-1],dp[1-con][j]);
dp[con][j] = MAX(tmp,dp[1-con][j+1]);
tmp = 0;
dp[con][j] += get_pros(i,j);
}
memcpy(dp[1-con],dp[con],sizeof(come));
con = 1 - con;
}
return 0;
}
int work()
{
int i,j,tmp;
_dp();
tmp = 0;
for(i = 0; i <= K; ++i)
tmp = MAX(tmp,dp[con][i]);
OUT(tmp);
return 0;
}
int main()
{
while(scanf("%d%d%d",&N,&K,&T)!=EOF)
{
init();
input();
work();
}
return 0;
}