JZOJ 4743 积木

一看数据范围,显然状压 DP。

考虑一下状态,设 \(f_{i,j,k}\) 表示选择的积木集合为 \(i\),最上面一个为 \(j\),第 \(k(0 \le k \le 2)\) 面朝上。
发现很可做,转移显然。

但是,发现非常的码农……
具体看代码(逃

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 15;
int n,ans;
int full;
struct note
{
int a,b,c;
} a[N + 5];
int f[(1 << N) + 10][N + 5][3];
int main()
{
scanf("%d",&n);
full = (1 << n) - 1;
for(register int i = 1;i <= n;++i)
{
scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
ans = max(ans,max(a[i].a,max(a[i].b,a[i].c)));
f[(1 << i - 1)][i][0] = a[i].c;
f[(1 << i - 1)][i][1] = a[i].a;
f[(1 << i - 1)][i][2] = a[i].b;
}
for(register int i = 0;i <= full;++i)
for(register int j = 1;j <= n;++j)
if(i & (1 << j - 1))
{
ans = max(ans,max(f[i][j][0],max(f[i][j][1],f[i][j][2])));
for(register int k = 1;k <= n;++k)
if(!(i & (1 << k - 1)))
{
if((a[k].a <= a[j].a && a[k].b <= a[j].b) || (a[k].b <= a[j].a && a[k].a <= a[j].b))
f[i | (1 << k - 1)][k][0] = max(f[i | (1 << k - 1)][k][0],f[i][j][0] + a[k].c);
if((a[k].b <= a[j].a && a[k].c <= a[j].b) || (a[k].c <= a[j].a && a[k].b <= a[j].b))
f[i | (1 << k - 1)][k][1] = max(f[i | (1 << k - 1)][k][1],f[i][j][0] + a[k].a);
if((a[k].a <= a[j].a && a[k].c <= a[j].b) || (a[k].c <= a[j].a && a[k].a <= a[j].b))
f[i | (1 << k - 1)][k][2] = max(f[i | (1 << k - 1)][k][2],f[i][j][0] + a[k].b);

if((a[k].a <= a[j].b && a[k].b <= a[j].c) || (a[k].b <= a[j].b && a[k].a <= a[j].c))
f[i | (1 << k - 1)][k][0] = max(f[i | (1 << k - 1)][k][0],f[i][j][1] + a[k].c);
if((a[k].b <= a[j].b && a[k].c <= a[j].c) || (a[k].c <= a[j].b && a[k].b <= a[j].c))
f[i | (1 << k - 1)][k][1] = max(f[i | (1 << k - 1)][k][1],f[i][j][1] + a[k].a);
if((a[k].a <= a[j].b && a[k].c <= a[j].c) || (a[k].c <= a[j].b && a[k].a <= a[j].c))
f[i | (1 << k - 1)][k][2] = max(f[i | (1 << k - 1)][k][2],f[i][j][1] + a[k].b);

if((a[k].a <= a[j].a && a[k].b <= a[j].c) || (a[k].b <= a[j].a && a[k].a <= a[j].c))
f[i | (1 << k - 1)][k][0] = max(f[i | (1 << k - 1)][k][0],f[i][j][2] + a[k].c);
if((a[k].b <= a[j].a && a[k].c <= a[j].c) || (a[k].c <= a[j].a && a[k].b <= a[j].c))
f[i | (1 << k - 1)][k][1] = max(f[i | (1 << k - 1)][k][1],f[i][j][2] + a[k].a);
if((a[k].a <= a[j].a && a[k].c <= a[j].c) || (a[k].c <= a[j].a && a[k].a <= a[j].c))
f[i | (1 << k - 1)][k][2] = max(f[i | (1 << k - 1)][k][2],f[i][j][2] + a[k].b);
}
}
printf("%d\n",ans);
}