http://codeforces.com/contest/112/problem/E
轮廓线dp。每一个格子中的蜘蛛选一个去向。终于,使每一个蜘蛛都有一个去向,同一时候保证有蜘蛛的格子最少。须要用4进制模拟
此题还能够用DLX+二分来解,这个解法相对于轮廓线dp就非常无脑了,不用考虑细节。以后再补上
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <cstdlib> #include <fstream> #include <vector> #include <set> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int maxn = 100010; int n, m; const int MALL = 1 << 14; int dp[2][MALL]; ///00 up, left; 01 stall; 10 right; 11 down; int now, next; int ALL; int ans; void update(int r, int nextr, int val) { nextr &= ALL; dp[next][nextr] = max(dp[next][nextr], dp[now][r] + val); } int getI(int x, int i) { return (x >> (2 * i))&3; } int main() { while (cin >> n >> m) { if (n < m) swap(n, m); ALL = (1 << (m * 2)) - 1; memset(dp, -1, sizeof(dp)); dp[0][0] = 0; now = 0; next = 1; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { for (int r = 0; r <= ALL; r++) { if (dp[now][r] != -1) if ((j && getI(r, 0) == 2) || (i && getI(r, m - 1) == 3)) { update(r, (r << 2) + 1, 0); continue; } update(r, (r << 2) + 1, 0); if (j && getI(r, 0) == 1 ) update(r, r << 2, 1);///left 00 if (i && getI(r, m - 1) == 1 ) update(r, r << 2, 1);///up 00 if (j < m - 1) update(r, (r << 2) + 2, 1);///right 10 if (i < n - 1) update(r, (r << 2) + 3, 1);///down 11 } memset(dp[now], -1, sizeof(dp[now])); next = now; now ^= 1; } } ans = 0; for (int i = 0; i <= ALL; i++) ans = max(ans, dp[now][i]); cout << ans << endl; } }
版权声明:本文博主原创文章。博客,未经同意不得转载。