題解 [POI2013]SPA-Walk
阿新 • • 發佈:2020-09-08
題目大意
給出兩個長度為 \(n\) 的 \(01\) 串,問是否可以通過某一位把 \(s\) 變為 \(t\),但是中途不能變為 \(k\) 個 \(01\) 串中任意一個,問是否可行。
\(n\le 60,n\times k\le 5\times 10^6\)
思路
拖了 1 年多,1 年前打了一個雙向 BFS ,騙了 \(60\) 分(為我後面看別人的 AC 程式碼打下了良好基礎 (倫敦霧,1 年後,在看了題解之後成功 A 掉此題,我成功了,我不再是以前的那個我了。
好吧,還是言歸正傳,其實這道題就是一個爆搜然後加上一個剪枝,剪枝就是說你最多隻搜 \(n\times k\) 個點,至於為什麼我就不知道了。(不過題面都給了 \(n\times k\le 5\times 10^5\)
\(\texttt{Code}\)
using namespace std; #define Int register int #define ll long long #define MAXN 5000005 #define MAXM 1000005 #define mod 2737321 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;} template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);} template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} ll a[MAXM],to[MAXN],q[MAXN]; int n,k,cnt,h,t,nxt[MAXN],head[mod + 5]; ll getins (){ ll s = 0; for (Int i = 0,x;i < n;++ i) scanf ("%1d",&x),s = (s << 1) | x; return s; } void ins (ll x){ to[++ cnt] = x,nxt[cnt] = head[x % mod],head[x % mod] = cnt; } void add (ll x){ for (Int i = head[x % mod];i;i = nxt[i]) if (to[i] == x) return ; ins (x),q[++ t] = x; } void BFS (ll S,ll T){ h = 1,t = cnt = 0; memset (head,0,sizeof (head)); for (Int i = 1;i <= k;++ i) ins (a[i]); add (S); while (h <= t && t <= n * k){ ll now = q[h ++]; if (now == T) puts ("TAK"),exit (0); for (Int i = 0;i < n;++ i) add (now ^ (1ll << i)); } if (t <= n * k) puts ("NIE"),exit (0); } signed main(){ read (n,k);ll S = getins (),T = getins (); for (Int i = 1;i <= k;++ i) a[i] = getins (); BFS (S,T),BFS (T,S); puts ("TAK"); return 0; }