• vijos 1464 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年全国青少年信息学(计算机)奥林匹克竞赛试题

    第二试

    大概就是个比较简单的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 }
  • 相关阅读:
    Git提交错了不用慌,这三招帮你修改记录
    codeforces 1443D,解法简单,思维缜密的动态规划问题
    为什么优秀的人总是少数?我从天文学当中获得了一些启示
    本科入行可能吗?做到这3点,斩获BAT offer不是梦
    裸考了一次雅思,我居然学会了数据分析!
    有了Git这个功能,再也不需要依赖IDE了!
    职场中究竟什么是ownership,你是一个有ownership的人吗?
    为何跳槽不考虑腾讯?聊聊我和鹅厂的一点往事
    【Azure DevOps系列】Azure DevOps EFCore命令式脚本部署到SQL数据库
    Linux查看、开启、关闭防火墙操作
  • 原文地址:https://www.cnblogs.com/Ateisti/p/6064800.html
Copyright © 2020-2023  润新知