背景
1997年全国青少年信息学(计算机)奥林匹克竞赛试题
第二试
描述
积木游戏
SERCOI 最近设计了一种积木游戏。每个游戏者有N块编号依次为1 ,2,…,N的长方
体积木。对于每块积木,它的三条不同的边分别称为"a边"、"b边"和"c边"
游戏规则如下:
1、从N块积木中选出若干块,并将它们分成M(l<=M<=N) 堆,称为第1堆,第2 堆…,第M堆。每堆至少有1块积木,并且第K堆中任意一块积木的编号要大于第K+1堆中任意一块积木的编号(2<=K<=M)。
2.对于每一堆积木,游戏者要将它们垂直摞成一根柱子,并要求满足下面两个条件:
(1)除最顶上的一块积木外,任意一块积木的上表面同且仅同另一块积木的下表面接触,并且要求下面的积木的上表面能包含上面的积木的下表面,也就是说,要求下面的积木的上表面的两对边的长度分别大于等于上面的积木的两对边的长度。
(2)对于任意两块上下表面相接触的积木,下面的积木的编号要小于上面的积木的编号。
最后,根据每人所摞成的M根柱子的高度之和来决出胜负。
请你编一程序,寻找一种摞积木的方案,使得你所摞成的M根柱子的高度之和最大。
格式
输入格式
第一行有两个正整数N和M(1<=M<=N<=100),分别表
示积木总数和要求摞成的柱子数。这两个数之间用一个空格符隔开。接下来N行依次是编号
从1到N的N个积木的尺寸,每行有三个;至1000之间的整数,分别表示该积木a边,b边
和c边的长度。同一行相邻两个数之间用一个空格符隔开。
输出格式
只有一行,为一个整数,表示M根柱子的高度之和。
限制
各个测试点1s
提示
1997年全国青少年信息学(计算机)奥林匹克竞赛试题
第二试
大概就是个比较简单的dp,f[i][a][b][k],表示考虑到第i堆,第a个积木,上一个放的是b,且b的k面朝上。
然后转移的话是三种状态,丢掉,f[i][a+1][b][k],放到i堆顶上f[i][a+1][a][k'](这里要枚举个k’),
以及重新放到其它堆上f[i+1][a+1][a][k'](同样要枚举个k)。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 const int N = 100 + 11; 5 using namespace std ; 6 int n,m,f[N][N][N][3],ans,inf; 7 struct Building 8 { 9 int h[3],x[3],y[3]; 10 } bks[N]; 11 12 void Init() 13 { 14 scanf("%d%d",&n,&m); 15 int x,y,h; 16 for(int i = 1;i <= n; ++i) 17 { 18 scanf("%d%d%d",&x,&y,&h); 19 bks[i].h[0] = h; 20 bks[i].x[0] = max(x,y), bks[i].y[0] = min(x,y); 21 bks[i].h[1] = x; 22 bks[i].x[1] = max(h,y), bks[i].y[1] = min(h,y); 23 bks[i].h[2] = y; 24 bks[i].x[2] = max(x,h), bks[i].y[2] = min(x,h); 25 } 26 } 27 28 int dp(int i,int a,int b,int k) 29 { 30 if(i>m||a>n)return 0; 31 if(~f[i][a][b][k]) return f[i][a][b][k]; 32 int ret = f[i][a][b][k] = 0; 33 ret = dp(i,a+1,b,k);//throw 34 for(int k2 = 0; k2 < 3 ; ++k2) 35 { 36 if(bks[b].x[k]>=bks[a].x[k2]&&bks[b].y[k]>=bks[a].y[k2]) 37 ret = max(ret,dp(i,a+1,a,k2)+bks[a].h[k2]);//top 38 if(i+1<=m) 39 ret = max(ret,dp(i+1,a+1,a,k2)+bks[a].h[k2]);//new 40 } 41 f[i][a][b][k] = ret ; 42 return f[i][a][b][k] = ret; 43 } 44 45 46 void Solve() 47 { 48 memset(f,-1,sizeof(f));//inf = f[1][1][1][1]; 49 bks[0].x[0] = bks[0].y[0] = 1013; 50 bks[0].x[1] = bks[0].y[1] = 1013; 51 bks[0].x[2] = bks[0].y[2] = 1013; 52 int ans = dp(1,1,0,0); 53 printf("%d ",ans); 54 55 } 56 57 58 59 int main( ) 60 { 61 // freopen("buildinggame.in","r",stdin); 62 // freopen("buildinggame.out","w",stdout); 63 Init(); 64 Solve(); 65 fclose(stdin); 66 fclose(stdout); 67 return 0; 68 }