Formula1 URAL1519

来源:互联网 发布:智能ip代理软件 编辑:程序博客网 时间:2024/06/11 18:55

这题可以说是正式的插头dp,需要对插头标号,虽然研读了hh的模板和论文,但写起来还是花了很多时间,主要是细节方面的东西,比如第一列和最后一列需要特殊讨论,还有最后一个合法格子也需要特殊讨论


#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <queue>#include <algorithm>#include <vector>#include <cstring>#include <stack>#include <cctype>#include <utility>   #include <map>#include <string>  #include <climits> #include <set>#include <string>    #include <sstream>#include <utility>   #include <ctime>using std::priority_queue;using std::vector;using std::swap;using std::stack;using std::sort;using std::max;using std::min;using std::pair;using std::map;using std::string;using std::cin;using std::cout;using std::set;using std::queue;using std::string;using std::istringstream;using std::make_pair;using std::getline;using std::greater;using std::endl;using std::multimap;using std::deque;typedef long long LL;typedef unsigned long long ULL;typedef pair<int, int> PAIR;typedef multimap<int, int> MMAP;const int MAXN(1000010);const int MAXM(10010);const int MAXE(10010);const int HSIZE(13131);const int SIGMA_SIZE(26);const int MAXH(19);const int INFI(2000000000);const int MOD(100000000);const ULL BASE(31);const LL LIM(10000000);const int INV(-10000);struct HASH_MAP{int first[HSIZE], next[MAXN];LL state[MAXN];LL value[MAXN];int  size;void init(){memset(first, -1, sizeof(first));size = 0;}void insert(LL ts, LL tv){int h = ts%HSIZE;for(int i = first[h]; ~i; i = next[i])if(state[i] == ts){value[i] += tv;return;}state[size] = ts;value[size] = tv;next[size] = first[h];first[h] = size++;}}hm[2];HASH_MAP *cur, *last;char mp[15][15];int code[13];int Num[13];inline void decode(int m, LL ts){for(int i = 0; i <= m; ++i){code[i] = ts&7;ts >>= 3;}}inline LL encode(int m){LL ret = 0;int cnt = 0;memset(Num, -1, sizeof(Num));for(int i = m; i >= 0; --i)if(code[i] == 0)ret <<= 3;else{if(Num[code[i]] < 0) Num[code[i]] = ++cnt;ret = (ret << 3)|Num[code[i]];}return ret;}int li, lj;inline bool lastgrid(int i, int j){ return i == li && j == lj;}void updata(int i, int j, int m, LL tv){int up = (i == 0)? 0: code[j+1];int left = (j == 0)? 0: code[j];if(mp[i][j] == '*'){if(up == 0 && left == 0){code[j] = code[j+1] = 0;cur->insert(encode(m), tv);}return;}if(up == 0 && left == 0) {if(j == m-1)         //最后一列不允许有右插头return;code[j] = code[j+1] = 7;}else if(up == 0 || left == 0) {code[j] = up+left;code[j+1] = 0;cur->insert(encode(m), tv);if(j == m-1)                    //最后一列不允许有右插头return;code[j] = 0;code[j+1] = up+left;cur->insert(encode(m), tv);return;}else if(up != left){if(lastgrid(i, j))return;for(int i = 0; i <= m; ++i)if(code[i] == up) code[i] = left;code[j] = code[j+1] = 0;}else if(lastgrid(i, j))      //只有最后一个格子允许连接成一条回路code[j] = code[j+1] = 0;elsereturn;cur->insert(encode(m), tv);}void solve(int n, int m){cur = hm;last = hm+1;last->init();last->insert(0, 1);for(int i = 0; i < n; ++i)for(int j = 0; j < m; ++j){cur->init();int sz = last->size;for(int k = 0; k < sz; ++k){decode(m, last->state[k]);if(j == 0)for(int k2 = m; k2 >= 1; --k2)   //另起一行时需要把编码整体右移code[k2] = code[k2-1];updata(i, j, m, last->value[k]);}if(lastgrid(i, j)){LL ans = 0;for(int i = 0; i < cur->size; ++i)if(cur->state[i] == 0){ans = cur->value[i];break;}printf("%I64d\n", ans);return;}swap(cur, last);}}int main(){int n, m;while(~scanf("%d%d", &n, &m)){for(int i = 0; i < n; ++i)scanf("%s", mp[i]);li = lj = -1;for(int i = n-1; i >= 0; --i){for(int j = m-1; j >= 0; --j)if(mp[i][j] == '.'){li = i;lj = j;break;}if(~li)break;}if(li == -1)printf("0\n");elsesolve(n, m);}return 0;}


括号表示法(对于回路问题效率要比最小表示法高)


#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <queue>#include <algorithm>#include <vector>#include <cstring>#include <stack>#include <cctype>#include <utility>   #include <map>#include <string>  #include <climits> #include <set>#include <string>    #include <sstream>#include <utility>   #include <ctime>using std::priority_queue;using std::vector;using std::swap;using std::stack;using std::sort;using std::max;using std::min;using std::pair;using std::map;using std::string;using std::cin;using std::cout;using std::set;using std::queue;using std::string;using std::istringstream;using std::make_pair;using std::getline;using std::greater;using std::endl;using std::multimap;using std::deque;typedef long long LL;typedef unsigned long long ULL;typedef pair<int, int> PAIR;typedef multimap<int, int> MMAP;const int MAXN(20010);const int MAXM(5010);const int MAXE(10010);const int HSIZE(13131);const int SIGMA_SIZE(26);const int MAXH(19);const int INFI((INT_MAX-1) >> 1);const int MOD(123456791);const ULL BASE(31);const LL LIM(10000000);const int INV(-10000);int N, M;char mp[15][15];struct HASH_MAP{int first[HSIZE];int next[MAXN], state[MAXN];LL value[MAXN];int size;void init(){memset(first, -1, sizeof(first));size = 0;}void insert(int ts, LL tv){int h = ts%HSIZE;for(int i = first[h]; ~i; i = next[i])if(state[i] == ts){value[i] += tv;return;}value[size] = tv;state[size] = ts;next[size] = first[h];first[h] = size++;}} hm[2];HASH_MAP *cur, *last;int acc[4] = {0, -1, 1, 0};  //无插头,左括号,右括号inline int getB(int ts, int i){ return (ts >> (i << 1))&3;}  //获得指定位inline int getLB(int ts, int i)   //通过右括号找到左括号{int ret = i, cnt = 1;while(cnt){--ret;cnt += acc[getB(ts, ret)];}return ret;}inline int getRB(int ts, int i)  //通过左括号找到右括号{int ret = i, cnt = -1;while(cnt){++ret;cnt += acc[getB(ts, ret)];}return ret;}inline void setB(int &ts, int i, int tv){ts = (ts&~(3 << (i << 1)))|(tv << (i << 1));}  //设置指定位int lx, ly;inline bool lastgrid(int x, int y){return x == lx && y == ly;}void updata(int x, int y, int ts, LL tv){int left = (y == 0)? 0: getB(ts, y);int up = (x == 0)? 0: getB(ts, y+1);int tts;if(mp[x][y] == '*'){if(left == 0 && up == 0){tts = ts;setB(tts, y, 0);setB(tts, y+1, 0);cur->insert(tts, tv);}return;}if(left == 0 && up == 0){if(x == N-1 || y == M-1) return;tts = ts;setB(tts, y, 1);setB(tts, y+1, 2);cur->insert(tts, tv);}elseif(left == 0 || up == 0){if(x < N-1){tts = ts;setB(tts, y, up+left);setB(tts, y+1, 0);cur->insert(tts, tv);}if(y < M-1){tts = ts;setB(tts, y, 0);setB(tts, y+1, up+left);cur->insert(tts, tv);}}else{tts = ts;setB(tts, y, 0);setB(tts, y+1, 0);if(left == 1 && up == 1){setB(tts, getRB(ts, y+1), 1);cur->insert(tts, tv);}else if(left == 1 && up == 2){if(!lastgrid(x, y)) return;cur->insert(tts, tv);}else if(left == 2 && up == 1){cur->insert(tts, tv);}else if(left == 2 && up == 2){setB(tts, getLB(ts, y), 2);cur->insert(tts, tv);}}}void solve(){cur = hm;last = hm+1;last->init();last->insert(0, 1);for(int i = 0; i < N; ++i){int sz = last->size;for(int k = 0; k < sz; ++k)last->state[k] <<= 2;for(int j = 0; j < M; ++j){cur->init();sz = last->size;for(int k = 0; k < sz; ++k)updata(i, j, last->state[k], last->value[k]);swap(cur, last);}}LL ans = 0;for(int i = 0; i < last->size; ++i)if(last->state[i] == 0){ans = last->value[i];break;}printf("%I64d\n", ans);}int main(){while(~scanf("%d%d", &N, &M)){for(int i = 0; i < N; ++i)scanf("%s", mp[i]);lx = -1;ly = -1;for(int i = N-1; i >= 0 && lx == -1; --i)for(int j = M-1; j >= 0; --j)if(mp[i][j] == '.'){lx = i;ly = j;break;}solve();}return 0;}



原创粉丝点击