标签:
[HNOI 2007]神奇游乐园
#include <bits/stdc++.h> #define maxn 110 using namespace std; typedef long long ll; int n, m; int a[maxn][maxn]; ll ans = -1ll << 60; #define M 2000010 #define mod 997 struct Hashmap{ ll st[M]; int h[1000], size, nxt[M]; ll f[M]; void clear(){memset(h, 0, sizeof h); size = 0;} void push(ll hash_, ll val){ int tmp = hash_ % mod; for(int i = h[tmp]; i; i = nxt[i]){ if(st[i] == hash_){ f[i] = max(f[i], val); return; } } int now = ++ size; f[now] = val; st[now] = hash_; nxt[now] = h[tmp]; h[tmp] = now; } }dp[2]; int cur, code[20], ch[20]; void Decode(ll st){ for(int i = m; i >= 0; i --) code[i] = st & 7, st >>= 3; } ll Encode(){ ll ret = 0; memset(ch, -1, sizeof ch); ch[0] = 0; int cnt = 0; for(int i = 0; i <= m; i ++){ if(ch[code[i]] == -1)ch[code[i]] = ++ cnt; code[i] = ch[code[i]]; ret = ret << 3 | code[i]; } return ret; } void Shift(){ for(int i = m; i >= 1; i --) code[i] = code[i-1]; code[0] = 0; } inline void Change(int u, int v){ for(int i = 0; i <= m; i ++) if(code[i] == v) code[i] = u; } void DP(int i, int j){ dp[cur^1].clear(); for(int k = 1; k <= dp[cur].size; k ++){ Decode(dp[cur].st[k]); if(j == 1){if(code[m])continue;Shift();} int Left = code[j-1], Up = code[j]; if(Left && Up){ code[j] = code[j-1] = 0; if(Left == Up){ ll ENCODE = Encode(); if(ENCODE == 0)ans = max(ans, dp[cur].f[k] + a[i][j]); } else{ Change(Left, Up); dp[cur^1].push(Encode(), dp[cur].f[k] + a[i][j]); } } else if(Left || Up){ int tmp = Left ? Left : Up; code[j-1] = 0, code[j] = tmp; dp[cur^1].push(Encode(), dp[cur].f[k] + a[i][j]); code[j] = 0, code[j-1] = tmp; dp[cur^1].push(Encode(), dp[cur].f[k] + a[i][j]); } else{ dp[cur^1].push(Encode(), dp[cur].f[k]); code[j] = code[j-1] = 8; dp[cur^1].push(Encode(), dp[cur].f[k] + a[i][j]); } } cur ^= 1; } int main(){ #ifndef ONLINE_JUDGE freopen("park.in","r",stdin); freopen("park.out","w",stdout); #endif scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) scanf("%d", &a[i][j]); dp[cur].clear(); dp[cur].push(0, 0); for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) DP(i, j); printf("%lld\n", ans); return 0; }
粘了一个模板上来=-=
基于连通性的动态规划,最小表示法很好用。
我们可以用一个压缩的数字表示一个连通情况,比如记录生成树,记录概率,记录棋盘上格子的情况,等等等
只要和连通性有关而且n很小时就可以用啦QAQ。
又忘了模板了QAQ
就是如果左边和上面是一个连通分量即Left == Up时,我们要合并连通分量,所以此时已经出现了一个圈了,这道题不能有多个圈,所以最后不放进去
code[j] = code[j-1] = 0.
标签:
原文地址:http://www.cnblogs.com/Candyouth/p/5392609.html