ecnu 1244 积木游戏(黑书)DP

dp[num][pos][pre][statu] 表示之前已经有num个堆,现在考虑第pos个长方体,且之前堆的最上面的长方体的下标为pre(用statu表示那一面朝上)之后还能获得的最大高度

对与目前的pos长方体,1.可以单独成堆,

                                         2.可以加入之前的堆(放在pre上面)

                                         3.或者直接丢掉

 这样就能向后转移了,我用的记忆话搜索来做的,这样比较简单,实在是不敢想象递推有多麻烦

AC代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

#define MAX 0x3f3f3f3f

struct Rectangle{
    int a, b, c;
};

int dp[110][110][110][3];
int N, M;
Rectangle r[110];

int geta( int pos, int statu ){
    int a = r[pos].a;
    int b = r[pos].b;
    int c = r[pos].c;

    if( statu == 0 ){
        return a > b ? a : b;
    }else if( statu == 1 ){
        return a > c ? a : c;
    }else{
        return b > c ? b : c;
    }
}

int getb( int pos, int statu ){
    int a = r[pos].a;
    int b = r[pos].b;
    int c = r[pos].c;

    if( statu == 0 ){
        return a > b ? b : a;
    }else if( statu == 1 ){
        return a > c ? c : a;
    }else{
        return b > c ? c : b;
    }
}

int DFS( int num, int pos, int pre, int statu ){
    if( pos > N ){
        return 0;
    }
    if( dp[num][pos][pre][statu] != -1 ){
        return dp[num][pos][pre][statu];
    }

    int ans = 0;
    //丢弃该长方体
    ans = max( ans, DFS( num, pos + 1, pre, statu ) );
    //该长方体独立成堆
    if( num < M ){
        ans = max( ans, r[pos].c + DFS( num + 1, pos + 1, pos, 0 ) );//c为高
        ans = max( ans, r[pos].b + DFS( num + 1, pos + 1, pos, 1 ) );//b为高
        ans = max( ans, r[pos].a + DFS( num + 1, pos + 1, pos, 2 ) );//a为高
    }
    //该长方体加入之前的堆
    int prea = geta( pre, statu );
    int preb = getb( pre, statu );
    int posa, posb;
    posa = geta( pos, 0 );
    posb = getb( pos, 0 );
    if( posa <= prea && posb <= preb ){//c为高
        ans = max( ans, r[pos].c + DFS( num, pos + 1, pos, 0 ) );
    }
    posa = geta( pos, 1 );
    posb = getb( pos, 1 );
    if( posa <= prea && posb <= preb ){//b为高
        ans = max( ans, r[pos].b + DFS( num, pos + 1, pos, 1 ) );
    }
    posa = geta( pos, 2 );
    posb = getb( pos, 2 );
    if( posa <= prea && posb <= preb ){//a为高
        ans = max( ans, r[pos].a + DFS( num, pos + 1, pos, 2 ) );
    }
    return dp[num][pos][pre][statu] = ans;
}

int main(){
    while( scanf( "%d%d", &N, &M ) != EOF ){
        r[0].a = r[0].b = r[0].c = MAX;
        for( int i = 1; i <= N; i++ ){
            cin >> r[i].a >> r[i].b >> r[i].c;
        }
        memset( dp, -1, sizeof( dp ) );
        cout << DFS( 1, 1, 0, 0 ) << endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值