noi1997 积木游戏

(http://www.elijahqi.win/2017/12/29/noi1997-%E7%A7%AF%E6%9C%A8%E6%B8%B8%E6%88%8F/)
积木游戏

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

输入输出

  输入文件是INPUT.TXT。文件的第一行有两个正整数N和M(1<=M<=N<=100),分别表

示积木总数和要求摞成的柱子数。这两个数之间用一个空格符隔开。接下来N行依次是编号

从1到N的N个积木的尺寸,每行有三个;至1000之间的整数,分别表示该积木a边,b边

和c边的长度。同一行相邻两个数之间用一个空格符隔开。

  输出文件是OUTPUT.TXT。文件只有一行,为一个整数,表示M根柱子的高度之和。

样例

INPUT.TXT

4 2

10 5 5

8 7 7

2 2 2

6 6 6

OUTPUT.TXT

24

题意:给定n块积木 要求分成m组 前面组的序号必须小于上一块积木的编号 并且处于上面个的积木的面的长度和宽度必须小于等于下面的

那么设f[i][j][k]表示 我当前处在第i堆 然后我现在用到第j个积木 然后我现在在处理第j个积木的第k个平面 那么显然 我可以自己另起炉灶或者继续搭在我现在这个木块的上面

如果是另起炉灶 那显然不需要考虑我上面的那块和前一块的长宽的大小了


#include<cstdio>
#include<algorithm>
#define N 110
using namespace std; 
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S) {T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0;char ch=gc();
    while(ch<'0'||ch>'9') ch=gc();
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
    return x;
}
int n,m,len[N][3],dp[N][N][3];
int main(){
    freopen("game.in","r",stdin);
    n=read();m=read();
    for (int i=1;i<=n;++i) len[i][0]=read(),len[i][1]=read(),len[i][2]=read();
    for (int i=1;i<=m;++i){
        for (int j=1;j<=n;++j){
            for (int k=0;k<j;++k){
                for (int z=0;z<=2;++z){
                    int a1=len[j][z],b1=len[j][(z+1)%3];
                    if (a1<b1) swap(a1,b1);
                    for (int l=0;l<=2;++l){
                        int a2=len[k][l],b2=len[k][(l+1)%3];
                        if (a2<b2) swap(a2,b2);
                        dp[i][j][z]=max(dp[i][j][z],dp[i-1][k][l]+len[j][(z+2)%3]);
                        if (a1>a2||b1>b2) continue;
                        dp[i][j][z]=max(dp[i][j][z],dp[i][k][l]+len[j][(z+2)%3]);
                    }
                }
            }
        }
    }int ans=0;
    for (int i=1;i<=n;++i) ans=max(max(dp[m][i][0],dp[m][i][1]),max(ans,dp[m][i][2]));
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值