BZOJ 1933 [Shoi2007]Bookcase 书柜的尺寸 ——动态规划
状态设计的方法很巧妙,六个值 h1,h2,h3,t1,t2,t3,我们发现t1,t2,t3可以通过前缀和优化掉一维。
然后考虑把h留下还是t留下,如果留下h显然t是会发生改变的,一个int存不下。
如果按照h降序排序,然后计算的时候存总的高度值,就很方便转移了。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define inf 0x3f3f3f3f int dp[2][2105][2105],n,sumt,prst[80]; struct Book{int h,t;}a[80]; bool cmp(Book x,Book y) {return x.h>y.h;} int main() { int now=1,pre=0; memset(dp[now],0x3f,sizeof dp[now]); dp[now][0][0]=0; scanf("%d",&n); F(i,1,n) scanf("%d%d",&a[i].h,&a[i].t),sumt+=a[i].t; sort(a+1,a+n+1,cmp); F(i,1,n) prst[i]=prst[i-1]+a[i].t; F(i,0,n-1) { now^=1;pre^=1; memset(dp[now],0x3f,sizeof dp[now]); F(j,0,sumt) F(k,0,sumt) if (dp[pre][j][k]!=inf) { if (j!=0) dp[now][j+a[i+1].t][k]=min(dp[now][j+a[i+1].t][k],dp[pre][j][k]); else dp[now][j+a[i+1].t][k]=min(dp[now][j+a[i+1].t][k],dp[pre][j][k]+a[i+1].h); if (k!=0) dp[now][j][k+a[i+1].t]=min(dp[now][j][k+a[i+1].t],dp[pre][j][k]); else dp[now][j][k+a[i+1].t]=min(dp[now][j][k+a[i+1].t],dp[pre][j][k]+a[i+1].h); if (prst[i]-j-k!=0) dp[now][j][k]=min(dp[now][j][k],dp[pre][j][k]); else dp[now][j][k]=min(dp[now][j][k],dp[pre][j][k]+a[i+1].h); } } int ans=inf; F(i,0,sumt) F(j,0,sumt) if (dp[now][i][j]!=inf) if (i*j*(prst[n]-i-j)!=0) { ans=min(ans,max(i,max(j,prst[n]-i-j))*dp[now][i][j]); } printf("%d\n",ans); }