题目:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=42067
思路:
将n本书分配到三层,使得形成的书架w*h最小
提前将书籍按照高度排序,因为无论第一本书(最高的书)无论放在那一层都会被考虑到,所以规定将它放在第一层,且第二层比第三层高。
因为从大到小排序的关系,只要jk==0那么新加入的书i就是该层的高度,否则高度不变。
设d[i][j][k]表示考虑过i本书第二层宽度为j第三层宽度为k时二三层的最小的高度和。
状态转移方程:(->表示更新)
d[i][j][k]->d[i+1][j][k]
d[i][j][k]+f(j,book[i].h)->d[i+1][j+book[i].w][k]
d[i][j][k]+f(k,book[i].h->d[i+1][j][k+book[i].w]
定义f(a,b):当a==0时return b esle return 0; 关于第一层,高度为book[0].h宽度为pre_w[n]-ww2-ww3;
优化:
代码:
1 #include<iostream> 2 #include<algorithm> 3 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 4 using namespace std; 5 6 const int maxn = 70 + 5; 7 const int maxw = 30; 8 const int INF = 1<<30; 9 10 struct Node{ 11 int w,h; 12 bool operator <(const Node& rhs) const { 13 return h>rhs.h || (h==rhs.h && w>rhs.w); 14 } 15 }book[maxn]; 16 17 int d[2][maxn*maxw][maxn*maxw]; 18 int pre_w[maxn]; 19 20 int n; 21 22 inline int f(int j,int h) { 23 return j==0? h:0; 24 } 25 inline void update(int& x,int v) { 26 if(x<0 || v<x) x=v; 27 } 28 29 int main() { 30 ios::sync_with_stdio(false); 31 32 int T; cin>>T; 33 while(T--) { 34 cin>>n; 35 FOR(i,0,n-1) cin>>book[i].h>>book[i].w; 36 sort(book,book+n); 37 pre_w[0]=0; 38 FOR(i,1,n) pre_w[i]=pre_w[i-1]+book[i-1].w; 39 40 d[0][0][0]=0; 41 int t=0; 42 FOR(i,0,n-1) { 43 FOR(j,0,pre_w[i+1]) 44 FOR(k,0,pre_w[i+1]-j) d[t^1][j][k]=-1; 45 46 FOR(j,0,pre_w[i]) 47 FOR(k,0,pre_w[i]-j) if(d[t][j][k]>=0){ 48 update(d[t^1][j][k],d[t][j][k]); 49 update(d[t^1][j+book[i].w][k],d[t][j][k]+f(j,book[i].h)); 50 update(d[t^1][j][k+book[i].w],d[t][j][k]+f(k,book[i].h)); 51 } 52 t^=1; 53 } 54 55 56 int ans=INF; 57 FOR(j,1,pre_w[n]) 58 FOR(k,1,pre_w[n]-j) if(d[t][j][k]>=0){ 59 int w=max(max(j,k),pre_w[n]-j-k); 60 int h=d[t][j][k]+book[0].h; 61 ans=min(ans,w*h); 62 } 63 cout<<ans<<"\n"; 64 } 65 return 0; 66 }