这题属于不必走完所有格子的一条回路问题,参考别人的思路,加了一个是否形成环的状态位,但效率好低啊,不知道括号表示法对这种问题效率如何。
#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(100010); const int MAXM(10010); 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(7777777); const ULL BASE(31); const LL LIM(10000000); const int INV(-10000); void checkmax(int &op1, int op2) {if(op2 > op1) op1 = op2;} struct HASH_MAP { int first[HSIZE], next[MAXN]; LL value[MAXN]; LL state[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; } value[size] = tv; state[size] = ts; next[size] = first[h]; first[h] = size++; } }hm[2]; HASH_MAP *cur, *last; int code[13]; int Num[9]; int N, M; char mp[15][15]; int circuit; bool can; void decode(LL ts) { for(int i = 0; i <= M; ++i) { code[i] = ts&7; ts >>= 3; } circuit = ts; } LL encode() { LL ret = 0; int cnt = 0; ret = circuit; 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 lx, ly; bool lastgrid(int x, int y) {return x == lx && y == ly;} void updata(int x, int y, LL tv) { int up = (x == 0)? 0: code[y+1]; int left = (y == 0)? 0: code[y]; if(mp[x][y] == 'X') { if(up == 0 && left == 0) { code[y] = code[y+1] = 0; cur->insert(encode(), tv); } return; } if(mp[x][y] == 'O') { if(lastgrid(x, y)) can = true; if(up == 0 && left == 0) { if(x == N-1 || y == M-1) return; code[y] = code[y+1] = 7; cur->insert(encode(), tv); } else if(up == 0 || left == 0) { if(x != N-1) { code[y] = up+left; code[y+1] = 0; cur->insert(encode(), tv); } if(y != M-1) { code[y] = 0; code[y+1] = up+left; cur->insert(encode(), tv); } } else if(left != up) { for(int i = 0; i <= M; ++i) if(code[i] == up) code[i] = left; code[y] = code[y+1] = 0; cur->insert(encode(), tv); } else if(can) { code[y] = code[y+1] = 0; circuit = 1; cur->insert(encode(), tv); } return; } if(up == 0 && left == 0) { code[y] = code[y+1] = 0; cur->insert(encode(), tv); if(x == N-1 || y == M-1 || circuit) return; code[y] = code[y+1] = 7; cur->insert(encode(), tv); } else if(up == 0 || left == 0) { if(circuit) return; if(x != N-1) { code[y] = up+left; code[y+1] = 0; cur->insert(encode(), tv); } if(y != M-1) { code[y] = 0; code[y+1] = up+left; cur->insert(encode(), tv); } } else if(up != left) { if(circuit) return; for(int i = 0; i <= M; ++i) if(code[i] == up) code[i] = left; code[y] = code[y+1] = 0; cur->insert(encode(), tv); } else if(can) { if(circuit) return; code[y] = code[y+1] = 0; circuit = 1; cur->insert(encode(), tv); } } void solve() { cur = hm; last = hm+1; last->init(); last->insert(0, 1); can = false; 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(last->state[k]); if(j == 0) for(int k2 = M; k2 >= 1; --k2) code[k2] = code[k2-1]; updata(i, j, last->value[k]); } swap(cur, last); } LL ans = 0; int temp = 3*(M+1); for(int i = 0; i < last->size; ++i) if(((1LL << temp)&last->state[i]) != 0 && (((1LL << temp)-1)&last->state[i]) == 0) { ans = last->value[i]; break; } printf("%I64d\n", ans); } int main() { int TC, n_case(0); scanf("%d", &TC); while(TC--) { 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] == 'O') { lx = i; ly = j; break; } printf("Case %d: ", ++n_case); solve(); } 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(200010); 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 CIR; inline int getCIR(int ts) {return (ts&CIR)? 1: 0;} inline void setCIR(int &ts, int tv) {ts = (ts&~CIR)|(tv? CIR: 0);} 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 circuit = getCIR(ts); int tts; if(mp[x][y] == 'X') { 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(mp[x][y] != 'O') { tts = ts; setB(tts, y, 0); setB(tts, y+1, 0); cur->insert(tts, tv); } if(x == N-1 || y == M-1 || (mp[x][y] == 'O' && circuit)) return; tts = ts; setB(tts, y, 1); setB(tts, y+1, 2); cur->insert(tts, tv); } else if(left == 0 || up == 0) { if(circuit) return; 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 { if(circuit) return; 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) { setCIR(tts, 1); 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); } } } template<typename T> void debug(const T &temp) { cout << temp << endl; } void solve() { CIR = (1 << ((M+1) << 1)); // debug(CIR); 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] = ((last->state[k] << 2)&(CIR-1))|(getCIR(last->state[k])? CIR: 0); 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] == CIR) { ans = last->value[i]; break; } printf("%I64d\n", ans); } int main() { int TC, n_case(0); scanf("%d", &TC); while(TC--) { scanf("%d%d", &N, &M); for(int i = 0; i < N; ++i) scanf("%s", mp[i]); printf("Case %d: ", ++n_case); solve(); } return 0; }