标签:
通道:http://acm.hdu.edu.cn/showproblem.php?pid=3377
题意:简单路径,从左上角走到右下角的最大权值,不需要每个格子都需要经过。
思路:初始化左上角上面那一格有下插头,然后一个不选状态,over.
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int MAX_N = 13; 8 const int MAX_M = 13; 9 const int HASH = 10007; 10 const int MAX_S = 1000007; 11 12 const int mov[20] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}; 13 14 struct node { 15 int head[HASH], nxt[MAX_S], cnt; 16 long long dp[MAX_S], st[MAX_S]; 17 void init() { 18 memset(head, -1, sizeof head); 19 cnt = 0; 20 } 21 void push(long long s, long long v) { 22 int now = s % HASH; 23 for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s) { 24 dp[i] = max(dp[i], v); 25 return ; 26 } 27 st[cnt] = s; dp[cnt] = v; 28 nxt[cnt] = head[now]; 29 head[now] = cnt++; 30 } 31 }d[2]; 32 33 int n, m; 34 35 int find_pos(long long s, int p) { 36 return s >> mov[p] & 3; 37 } 38 39 void tp(long long &s, int p, long long v) { 40 s &= ~(3ll << mov[p]); 41 s |= v << mov[p]; 42 } 43 44 int find_r(long long s, int p) { 45 int cnt = 0; 46 for(int i = p; i <= m; ++i) { 47 if(find_pos(s, i) == 1) ++cnt; 48 else if(find_pos(s, i) == 2) --cnt; 49 if(!cnt) return i; 50 } 51 } 52 53 int find_l(long long s, int p) { 54 int cnt = 0; 55 for(int i = p; i >= 0; --i) { 56 if(find_pos(s, i) == 2) ++cnt; 57 else if(find_pos(s, i) == 1) --cnt; 58 if(!cnt) return i; 59 } 60 } 61 62 int a[MAX_N][MAX_M]; 63 long long ans; 64 65 void blank(int i, int j, int cur) { 66 for(int k = 0; k < d[cur].cnt; ++k) { 67 long long t = d[cur].st[k]; 68 int l = find_pos(t, j - 1), r = find_pos(t, j); 69 if (i == n && j == m) { 70 if (l || r) { 71 if (!(l && r)) 72 ans = max(ans, d[cur].dp[k] + a[i][j]); 73 } 74 continue; 75 } 76 if(l && r) { 77 if(l == 1 && r == 1) { 78 int tpos = find_r(t, j); 79 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1); 80 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 81 } else if(l == 2 && r == 1) { 82 tp(t, j - 1, 0); tp(t, j, 0); 83 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 84 } else if(l == 2 && r == 2) { 85 int tpos = find_l(t, j - 1); 86 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2); 87 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 88 } else { // 最后一个非障碍格子 89 continue; 90 } 91 } else if(l) { 92 if(i < n) { 93 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 94 } 95 if(j < m) { 96 tp(t, j - 1, 0); tp(t, j, l); 97 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 98 } 99 } else if(r) { 100 if(j < m) { 101 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 102 } 103 if(i < n) { 104 tp(t, j - 1, r); tp(t, j, 0); 105 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 106 } 107 } else { // 新建 108 d[cur ^ 1].push(t, d[cur].dp[k]); 109 if(i < n && j < m) { 110 tp(t, j - 1, 1); tp(t, j, 2); 111 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 112 } 113 } 114 } 115 } 116 117 int main() { 118 int cas = 0; 119 while (2 == scanf("%d%d", &n, &m)) { 120 for (int i = 1; i <= n; ++i) { 121 for (int j = 1; j <= m; ++j) 122 scanf("%d", &a[i][j]); 123 } 124 125 ans = -(int)1e9; 126 int cur = 0; 127 d[cur].init(); 128 d[cur].push(1, 0); 129 for (int i = 1; i <= n; ++i) { 130 for (int j = 1; j <= m; ++j) { 131 d[cur ^ 1].init(); 132 blank(i, j, cur); 133 cur ^= 1; 134 } 135 for (int j = 0; j < d[cur].cnt; ++j) 136 d[cur].st[j] <<= 2; 137 } 138 printf("Case %d: %I64d\n", ++cas, ans); 139 } 140 return 0; 141 }
标签:
原文地址:http://www.cnblogs.com/Rojo/p/4640692.html