神奇的dp优化。
考虑6维状态的dp,分别表示三行高和宽,显然MLE&&TLE。
把高排个序,从大到小往架上放,那么若不是重开一行便对高度没有影响。
然后求出宽度的sum,dp[i][j]表示第一行放了i的宽度,二行放了j的宽度,三行放了sum-i-j宽度的最小的高度值。
先把所有书放在第三行,然后从第二本开始转移,考虑往其他行移的情况。
避免MLE要滚动数组。
注意最后更新答案时保证i>0&&j>0&&sum-i-j>0且dp[i][j]!=INF;
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<ctime> typedef long long LL; using namespace std; int n,sum,f[2][2150][2150],ans=1e9; struct book { int hi,ti; friend bool operator <(const book &A,const book &B) { return A.hi>B.hi; } }bk[75]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&bk[i].hi,&bk[i].ti); sort(bk+1,bk+n+1); for(int i=1;i<=n;i++) sum+=bk[i].ti; int o=0; memset(f,127/3,sizeof(f)); f[0][0][0]=bk[1].hi; for(int i=2;i<=n;i++) { o^=1; for(int j=0;j<=sum;j++) { for(int k=0;k<=sum&&j+k<sum;k++) { f[o][j][k]=min(f[o][j][k],f[o^1][j][k]); if(!j) f[o][j+bk[i].ti][k]=min(f[o][j+bk[i].ti][k],f[o^1][j][k]+bk[i].hi); else f[o][j+bk[i].ti][k]=min(f[o][j+bk[i].ti][k],f[o^1][j][k]); if(!k) f[o][j][k+bk[i].ti]=min(f[o][j][k+bk[i].ti],f[o^1][j][k]+bk[i].hi); else f[o][j][k+bk[i].ti]=min(f[o][j][k+bk[i].ti],f[o^1][j][k]); if(i==n&&j!=0&&k!=0&&f[o][j][k]!=707406378) { ans=min(ans,f[o][j][k]*max(max(j,k),sum-j-k)); } } } } printf("%d\n",ans); return 0; }
时间: 2024-10-01 16:12:16