【NOIP2016提高A组模拟9.2】积木

题目

Description

这里写图片描述
Input
这里写图片描述
Sample Input

3
8 7 6
3 9 4
1 10 5
Output

Sample Output

18
这里写图片描述
Data Constraint
这里写图片描述

题目大意

给你一些方块,给出每个方块的长宽高,可以以任意一面为底面,用任意的顺序选择任意一些方块,下面的方块一定要完全包含上面的方块(下面方块的长,宽分别小于上面方块的长宽)。求最高的搭出积木的高度

比赛时の想法

看到这个数据范围,就想到状压DP,状态也是很好设的,我们设f[s,i,j,k]表示当前方块的选取状态为s,当前在最上面的方块是i,它的长和宽分别是j和k(由于一个方块只有3个长度,所以j,k的范围都是1-3的)。转移的话也很简单,我们先确定要添加的一个方块,然后再确定当前在最上面的方块,最后再确定两个方块以哪一位为底面就可以了。那么时间复杂度 O(2n1n29)

正解

在上面

贴代码

var
    f:array[0..65540,1..15,1..3,1..3]of longint;
    a:array[0..15,1..3]of longint;
    g:array[0..20]of longint;
    i,j,k,l,n,x,y,ans:longint;
function max(x,y:longint):longint;
begin
    if x>y then exit(x) else exit(y);
end;
procedure init;
begin
    g[1]:=1;
    for i:=2 to 20 do g[i]:=g[i-1]*2;
    readln(n);
    for i:=1 to n do
    begin
        readln(a[i,1],a[i,2],a[i,3]);
        f[g[i],i,1,2]:=a[i,3];
        f[g[i],i,1,3]:=a[i,2];
        f[g[i],i,2,3]:=a[i,1];
        f[g[i],i,2,1]:=a[i,3];
        f[g[i],i,3,1]:=a[i,2];
        f[g[i],i,3,2]:=a[i,1];
    end;
end;
begin
    init;
    for i:=1 to g[n+1]-2 do
    begin
        for j:=1 to n do
        if g[j] and i=0 then
        begin
            for k:=1 to n do
            if g[k] and i<>0 then
            begin
                for x:=1 to 3 do
                begin
                    for y:=1 to 3 do
                    if x<>y then
                    begin
                        if (a[j,1]<=a[k,x]) and (a[j,2]<=a[k,y]) and (f[i,k,x,y]>0) then
                        f[i+g[j],j,1,2]:=max(f[i+g[j],j,1,2],f[i,k,x,y]+a[j,3]);
                        if (a[j,2]<=a[k,x]) and (a[j,1]<=a[k,y]) and (f[i,k,x,y]>0) then
                        f[i+g[j],j,2,1]:=max(f[i+g[j],j,2,1],f[i,k,x,y]+a[j,3]);
                        if (a[j,1]<=a[k,x]) and (a[j,3]<=a[k,y]) and (f[i,k,x,y]>0) then
                        f[i+g[j],j,1,3]:=max(f[i+g[j],j,1,3],f[i,k,x,y]+a[j,2]);
                        if (a[j,3]<=a[k,x]) and (a[j,1]<=a[k,y]) and (f[i,k,x,y]>0) then
                        f[i+g[j],j,3,1]:=max(f[i+g[j],j,3,1],f[i,k,x,y]+a[j,2]);
                        if (a[j,2]<=a[k,x]) and (a[j,3]<=a[k,y]) and (f[i,k,x,y]>0) then
                        f[i+g[j],j,2,3]:=max(f[i+g[j],j,2,3],f[i,k,x,y]+a[j,1]);
                        if (a[j,3]<=a[k,x]) and (a[j,2]<=a[k,y]) and (f[i,k,x,y]>0) then
                        f[i+g[j],j,3,2]:=max(f[i+g[j],j,3,2],f[i,k,x,y]+a[j,1]);
                    end;
                end;
            end;
        end;
    end;
    for i:=1 to g[n+1]-1 do
    begin
        for j:=1 to n do
        for x:=1 to 3 do
            for y:=1 to 3 do
            if x<>y then
            begin
                if f[i,j,x,y]>ans then ans:=f[i,j,x,y];
            end;
    end;
    writeln(ans);
end.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值