题意
有若干的方块堆叠,长宽均小于等于下面的方块,才能堆叠上去。方块可以任意旋转(长宽高任意切换)。每个输入的方块只能使用一次,但是多个输入的方块可以有相同长宽高。求可能堆叠的最高高度。
输入:
N(方块数目,1<=N<=20)
x1 y1 z1(第一个方块的长宽高)
x2 y2 z2(第二个方块的长宽高)
…
xN yN zN(第N个方块的长宽高)
输出:
Hmax
示例
示例1:
输入:
1
4 7 8
输出
8
实例2:
输入:
3
1 2 3
1 3 2
3 2 1
输出:
9
实例3:
输入:
3
55 10 9
4 7 8
1 3 2
输出:
66
分析
如果直接DFS,会超时
(20个方块*3个面,60树枝,20树层,60!)
–》
使用MEMO
–》
MEMO[1<<60]太大
–》
MEMO[20][3][1 << 20]
MEMO[20][3][1 << 20] 的说明:
已选择的方块[101011]
最上面的是[20][3] 有20种*3面
转移方程:已选方块去除最上面的,剩下的已选方块,每个都尝试一下,能不能将去除的方块放在自己上面。
MEMO[6][0][10111100], 10111100去掉第六块,变成00111100
00111100,第3、4、5、6块每个方块、每个面,都尝试看看能不能把[6][0]放在自己上面
MEMO[3][0][00111100]
MEMO[3][1][00111100]
MEMO[3][2][00111100]
MEMO[4][0][00111100]
MEMO[4][1][00111100]
MEMO[4][2][00111100]
MEMO[5][0][00111100]
MEMO[5][1][00111100]
MEMO[5][2][00111100]
MEMO[6][0][00111100]
MEMO[6][1][00111100]
MEMO[6][2][00111100]
这些取最大值
题解
#define MIN(a,b) (a)<(b)?(a):(b)
#define MAX(a,b) (a)>(b)?(a):(b)
int memo[20][3][1 << 20] = { 0 };
int N;
int cube[20][3];
bool inState(int i,int S)
{
if ((S & (1 << i) )== 0)
return false;
return true;
}
int addState(int i, int S) { S = (S | (1 << i)); return S; }
int delState(int i, int S) { S -= (S & (1 << i)); return S;}
bool PutBelow(int cubup, int rotateup, int cubbelow, int rotatebelow)
{
int x1 = cube[cubup][(rotateup + 1) % 3];
int y1 = cube[cubup][(rotateup + 2) % 3];
int x2 = cube[cubbelow][(rotatebelow + 1) % 3];
int y2 = cube[cubbelow][(rotatebelow + 2) % 3];
if (x1 <= x2 && y1 <= y2 )
{
return true;
}
if (y1 <= x2 && x1 <= y2)
{
return true;
}
return false;
}
//curstate,last cub is cubNum of rotate,return MaxRes
//N=4 1 2 3 4 5 6 7 8 9 3 3 3
//curstate=6->0110->cub1 cub2 is selected, cub0,cub3 is not
//cubNum =1,rotate=1-->cub1 is at rear,height is 8;lenth and width is at ease
int dfs(int cubNum,int rotate,int curstate)
{
if (memo[cubNum][rotate][curstate] != 0)return memo[cubNum][rotate][curstate];
int Nextstate = delState(cubNum, curstate);
if (Nextstate == 0)
{
memo[cubNum][rotate][curstate] = cube[cubNum][rotate];
return memo[cubNum][rotate][curstate];
}
int k = 0;
int res = -1;
int nextrot;
for (k = 0; k < N; k++)
{
if(inState(k, Nextstate))
for (nextrot=0; nextrot<3; nextrot++)
{
if (true==PutBelow(cubNum, rotate, k, nextrot))
res = MAX(res, dfs(k, nextrot, Nextstate));
}
if (Nextstate < (1 << k))break;
}
if (res != -1)
{
memo[cubNum][rotate][curstate] = res+cube[cubNum][rotate];
return memo[cubNum][rotate][curstate];
}
if (res == -1)
return memo[cubNum][rotate][curstate] =-1;
}
void input()
{
int i = 0;
scanf("%d",&N);
for (i = 0; i < N; i++)
{
scanf("%d", &cube[i][0]);
scanf("%d", &cube[i][1]);
scanf("%d", &cube[i][2]);
}
}
/*
1
4 7 8
1
7 8 4
1
8 4 7
3
55 10 9 4 7 8 1 3 2
3
1 2 3 1 3 2 1 2 3
15
55 10 9 4 7 8 1 3 2 44 43 45 22 21 24 1 28 88 6 1 26 34 41 67 2 56 73 43 45 22 21 24 1 28 4 88 6 1 26 13 35 77 23 4 9
*/
int main()
{
input();
int statenum = 1 << N;
int i;
int j;
int rotate = 0;
int res = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < statenum; j++) //00 01 10 11 -->4==1<<2-->0-3
{
if (false == inState(i, j))
continue;
for (rotate = 0; rotate < 3; rotate++)
{
res = MAX(res, dfs(i, rotate,j));
}
}
}
return res;
}