Live2D

题解 [POI2013]SPA-Walk

题目传送门

题目大意

给出两个长度为 \(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;
}
posted @ 2020-09-08 21:10  Dark_Romance  阅读(173)  评论(0编辑  收藏  举报