Vijos P1464 积木游戏(动态规划)

P1464积木游戏
Accepted
标签: 动态规划 NOIP提高组1997

背景

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根柱子的高度之和。

样例1

样例输入1[复制]

4 2
10 5 5
8 7 7
2 2 2
6 6 6

样例输出1[复制]

24

限制

各个测试点1s

提示

1997年全国青少年信息学(计算机)奥林匹克竞赛试题

第二试

思路

1)题目中对编号有要求,第k堆中任意一块积木的编号要大于第k+1堆中任意一块积木,每一堆中,下面的积木编号要小于上面的积木编号,也就是说,对于所给的积木,可以取或不取,但只能按顺序取,按顺序堆
2)对积木大小的要求,每一堆下面的积木要比上面的大
3)用DP,对m堆,n块积木枚举,在满足编号要求的前提下,枚举每一块积木的三条边
4)用f[i][j][l]表示第i堆第j块积木第l条边的最大高度
5)样例输出:
     第一堆,一块积木(10,5,5),高度为10
     第二堆,两块积木(8,7,7)(6 ,6,6),高度14

代码

#include 
using namespace std;
const int N=110;
int a[N][3],ans;
int dp[N][N][3],n,m,x1,y1,x2,y2;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
     cin>>a[i][0]>>a[i][1]>>a[i][2];
    for(int i=1;i<=m;i++)		//第i根柱子 
        for(int j=1;j<=n;j++)		//第j块积木 
            for(int h=0;h=x2&&y1>=y2)			//如果下面积木的两条边大于上面积木的两边 
                            dp[i][j][l]=max(dp[i][j][l],dp[i][h][k]+a[j][(l+2)%3]);  //放或不放,取较大佱 
                        dp[i][j][l]=max(dp[i][j][l],dp[i-1][h][k]+a[j][(l+2)%3]);	//和前一堆比较 
                        ans=max(ans,dp[i][j][l]);
                    }
    cout<




你可能感兴趣的:(动态规划)