EOJ:Roller Coaster
——贝茜滑冰,一共有n段。每段或者睁眼或者闭眼。如果一段睁着眼则好感度和晕眩度增加,若闭眼则好感度不变,晕眩度下降。求在不超过晕眩度上限的情况下获得的做大好感度。
——背包问题,注意维度表示的量
——http://202.120.106.94/onlinejudge/problemshow.php?pro_id=589
————————————————————————————————————————————————
首先,大家都能想到的方程:DP[I][J]表示第I个物品晕眩度为J时能获得的最大好感度。
但是由于原题中I<=1000而J<=300000,所以这个转移铁定超时。
————————————————————————————————————————
注意到好感度最多为20*1000=20000
因此转换维度
DP[I][J]表示第I个物品好感度为J是的最小晕眩度。
注意当DP[I][J]>limit的时候,不能用于进行转移
#include<stdio.h> #define N 1001 #define oo 0x7ffffff int dp[2][N*20],f[N],d[N]; int n,k,l,i,j,r,nr,up_bound,maxm; int min(int a,int b) { return a<b?a:b; } int main() { while (1) { scanf("%d%d%d",&n,&k,&l); if (n==0) break; for (i=0;i<=1;i++) for (j=0;j<=n*20;j++) dp[i][j]=oo; for (i=1;i<=n;i++) scanf("%d%d",&f[i],&d[i]); dp[0][0]=0; r=1; nr=0; up_bound=0; maxm=0; for (i=0;i<n;i++) { r=(r+1)%2; nr=(nr+1)%2; for (j=0;j<=up_bound;j++) if (dp[r][j]<=l) { dp[nr][j+f[i+1]]=min(dp[nr][j+f[i+1]],dp[r][j]+d[i+1]); dp[nr][j]=min(dp[nr][j],dp[r][j]-k); if (dp[nr][j]<0) dp[nr][j]=0; if (dp[nr][j+f[i+1]]<=l&&j+f[i+1]>maxm) maxm=j+f[i+1]; } up_bound=maxm; } printf("%d\n",maxm); } return 0; }