codevs 5059 一起去打CS
/*
空间32000 我写的全都31900+ 醉了 可以降维优化空间的 状态:f[i][j] 前i个题目a一共做了j分钟 b最少的做题时间 转移:考虑每个题目给谁做 f[i][j] = min ( f[i-1][j-a]a做 , f[i-1][j]+b b做); 最后对于f[n]枚举a的做题时间 更新答案 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 201 using namespace std; int n,a,b,sum,ans=0x3f3f3f3f,f[maxn][maxn*maxn]; int main() { scanf("%d",&n); memset(f,127/3,sizeof(f));f[0][0]=0; for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b);sum+=b; f[i][0]=sum; for(int j=0;j<=40000;j++) if(j>=a)f[i][j]=min(f[i-1][j-a],f[i-1][j]+b); else f[i][j]=f[i-1][j]+b; } for(int i=1;i<=40000;i++) ans=min(ans,max(i,f[n][i])); printf("%d\n",ans); return 0; }
/*滚动数组版本*/ #include<iostream> #include<cstdio> #include<cstring> #define maxn 200 using namespace std; int n,a[maxn+10],b[maxn+10],f[2][maxn*maxn+10],ans=0x3f3f3f3f; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); memset(f,127/3,sizeof(f)); f[0][0]=0; for(int i=1;i<=n;i++) { for(int j=maxn*maxn;j>=0;j--) { if(j>=a[i])f[i&1][j]=min(f[i&1][j],f[(i-1)&1][j-a[i]]); f[i&1][j]=min(f[i&1][j],f[(i-1)&1][j]+b[i]); if(i==n)ans=min(ans,max(f[i&1][j],j)); } for(int j=maxn*maxn;j>=0;j--) f[(i-1)&1][j]=0x3f3f3f3f; } printf("%d\n",ans); return 0; }