HDU 4026【状态压缩DP+判断路径可达】

题意:

玩过Android吧,有个叫图案屏锁的。这题求连接所有的点能产生的图案锁的个数。输入n,m表示图案为n*m的规模(n,m<=5),然后输入一个n*m的矩阵g,g[i][j]表示该点的类型,为0时表示普通的点能触点能滑动,但不能跨,为1时这个点不能被点击和滑过,为2时表示这点能跨过但不能触点。求连接所有的普通点能构成多少个图。 p="">

解题思路:

网络赛时没看过这题,如果看了相信会花一个下午的时间钻在这题上,状态压缩DP是我最想征服的类型。这跟哈密顿图的解法差不多,其实就是求哈密顿通路个数吧。DP[i][s],表示以结点i为最后一个连接点路径状态为s时的图像个数。转移式为DP[i][s] = DP[1][s ^ (1 << i)] + DP[2][s ^ (1 << i)] + ...DP[n][s ^ (1 << i)]。最后所有的DP[k][(1 << n + 1) - 1]求和为解。在判定i,j两点是否可达时应预先处理,否则很容易TLE。另外'&'这运算符的级别超低,最好每个运算式都加括号。

View Code
  1 #include <iostream>
2 #include <cstdio>
3 #include <string>
4 #include <cstring>
5 #include <cstring>
6 #include <algorithm>
7 #include <vector>
8 #include <map>
9
10 using namespace std;
11
12 const int MAX = 30;
13 int n, m;
14 int G[MAX];
15 int SHash[MAX];
16 int NHash[MAX];
17 int D[MAX][MAX];
18 int S[MAX][MAX];
19 long long DP[17][1 << 17];
20
21 bool isInline(int x1, int y1, int x2, int y2, int x3, int y3)
22 {
23 return (y2 - y1) * (x3 - x1) == (y3 - y1) * (x2 - x1);
24 }
25
26 void exchange(int& a, int& b)
27 {
28 int t = a;
29 a = b;
30 b = t;
31 }
32
33 void build(int e)
34 {
35 memset(D, 0, sizeof(D));
36 memset(S, 0, sizeof(S));
37 for(int i = 0; i < e; ++i)
38 {
39 for(int j = i + 1; j < e; ++j)
40 {
41 int from = SHash[j];
42 int to = SHash[i];
43 if(from > to)
44 exchange(from, to);
45 int xf = from / m;
46 int yf = from % m;
47 int xt = to / m;
48 int yt = to % m;
49 for(int k = from + 1; k < to; ++k)
50 {
51 int xk = k / m;
52 int yk = k % m;
53 if(isInline(xf, yf, xt, yt, xk, yk))
54 {
55 if(G[k] == 1)
56 {
57 D[i][j] = D[j][i] = -1;
58 break;
59 }
60 if(G[k] == 0)
61 {
62 S[i][j] |= (1 << NHash[k]);
63 S[j][i] |= (1 << NHash[k]);
64 }
65 }
66 }
67 }
68 }
69 }
70 bool canReach(int i, int j, int s)
71 {
72 if(D[i][j] == -1)
73 return false;
74 if((s & S[i][j]) != S[i][j])
75 return false;
76 return true;
77 }
78
79 int main()
80 {
81 // freopen("in.txt","r",stdin);
82 int i, e, s, j, k;
83 while(scanf("%d%d", &n, &m) == 2)
84 {
85 int num = n * m;
86 for(i = 0, e = 0; i < num; ++i)
87 {
88 scanf("%d", &G[i]);
89 if(G[i] == 0)
90 {
91 SHash[e] = i;
92 NHash[i] = e++;
93 }
94 }
95 build(e);
96 int end = 1 << e;
97 for(s = 1; s < end; ++s)
98 {
99 for(i = 0; i < e; ++i)
100 {
101 if(s == (1 << i))
102 DP[i][s] = 1;
103 else
104 DP[i][s] = 0;
105 if((s & (1 << i)) > 0)
106 {
107 for(j = 0; j < e; ++j)
108 {
109 if(j != i && (s & (1 << j)) > 0)
110 {
111 if(canReach(i, j, s))
112 {
113 DP[i][s] += DP[j][s - (1 << i)];
114 }
115 }
116 }
117 }
118 }
119 }
120 long long ans = 0;
121 for(i = 0; i < e; ++i)
122 {
123 ans += DP[i][end - 1];
124 }
125 printf("%I64d\n", ans);
126 }
127 return 0;
128 }



posted on 2011-09-27 01:08  Kenfly  阅读(678)  评论(0编辑  收藏  举报