1393: [Ceoi2008]knights

    xiaoxiao2021-03-25  104

    题意:

    在一块N*N的棋盘上有K个骑士,它们只能朝四个方向移动,每一回合,玩家必须把所有能动的骑士移动一格,当一个玩家没有任何骑士可以移动的时候它就输了,问是否先手必胜,如果是,给出一种可行的每个棋子的第一步的方案。

    solution:

    这是一个every-sg游戏,对于每个局面,如果先手必胜,那么先手必定是想尽可能地多走几步,否则,先手肯定是想尽可能早地结束这场游戏。

    那么定义stepi,为局面i执行最优决策时的步数。对于所有局面,先手必胜,当且仅当先手必胜局中step的最大值大于先手必败局中step的最大值,证明很显然的。。。

    最后打表找找这张图中sg值和step值的规律就行了

    先看先手必败点的分布,总结一下sg值,总结一下step即可

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<vector> #include<queue> #include<set> #include<map> #include<stack> #include<bitset> #include<ext/pb_ds/priority_queue.hpp> using namespace std; const int maxn = 2E5 + 20; const int INF = ~0U>>1; const int dx[4] = {-2,-2,-1,1}; const int dy[4] = {1,-1,-2,-2}; struct Point{ int x,y; Point(){} Point(int x,int y): x(x),y(y){} }p[maxn]; int n,m,Win,Lose; inline int getint() { char ch = getchar(); int ret = 0; while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') ret = ret * 10 + ch - '0',ch = getchar(); return ret; } char s[10]; inline void Print(int x) { int len = 0; while (x) s[++len] = x % 10,x /= 10; for (int i = len; i; i--) putchar(s[i] + '0'); } inline int min(const int &x,const int &y) {return x < y ? x : y;} inline int max(const int &x,const int &y) {return x > y ? x : y;} inline int Sg(int x,int y) { if (n % 4 == 0 && x == n && y == n) return 0; if (n % 4 == 1 && x == n && y != n - 1) return 0; if (n % 4 == 1 && x != n - 1 && y == n) return 0; if ((x % 4 == 1 || x % 4 == 2) && (y % 4 == 1 || y % 4 == 2)) return 0; return 1; } inline int LoseStep(int x,int y) { return (x + y - ((x == n || y == n) ? 2 : 1)) / 4 * 2; } inline int WinStep(int x,int y) { int ret = 0; for (int i = 0; i < 4; i++) { int xx = x + dx[i],yy = y + dy[i]; if (xx < 1 || xx > n || yy < 1 || yy > n) continue; if (Sg(xx,yy)) continue; ret = max(ret,LoseStep(xx,yy)); } return ret + 1; } void Print_Ans() { for (int i = 1; i <= m; i++) Print(p[i].x),putchar(' '),Print(p[i].y),puts(""); } int main() { #ifdef DMC freopen("DMC.txt","r",stdin); #endif cin >> m >> n; for (int i = 1; i <= m; i++) { int x = getint(),y = getint(); int sg = Sg(x,y),tmp; if (sg) { tmp = -1; for (int j = 0; j < 4; j++) { int xx = x + dx[j],yy = y + dy[j]; if (xx < 1 || xx > n || yy < 1 || yy > n) continue; if (Sg(xx,yy)) continue; int now = LoseStep(xx,yy); if (now > tmp) p[i] = Point(xx,yy),tmp = now; } Win = max(Win,tmp + 1); } else { tmp = INF; for (int j = 0; j < 4; j++) { int xx = x + dx[j],yy = y + dy[j]; if (xx < 1 || xx > n || yy < 1 || yy > n) continue; int now = WinStep(xx,yy); if (now < tmp) p[i] = Point(xx,yy),tmp = now; } Lose = max(Lose,tmp + 1); } } if (Win < Lose) puts("NO"); else puts("YES"),Print_Ans(); return 0; } 

    转载请注明原文地址: https://ju.6miu.com/read-23796.html

    最新回复(0)