zoukankan      html  css  js  c++  java
  • CF1201E2

    CF1201E2 - Knightmare (hard)

    题目大意

    (n imes m(2|n,2|m))的棋盘上有两个 马 (Knight是国际象棋) 分别位于(S_1=(x_1,y_1),S_2=(x_2,y_2))

    他们分别要到达(T_1=(frac{n}{2},frac{m}{2}),T_2=(frac{n}{2}+1,frac{m}{2}))

    一方胜利的情况是:

    1.吃掉另一方

    2.到达自己的目标位置,且这个位置不能被另一方吃掉

    你可以选定操作先手还是后手,要求和交互器交互,并且在350步内取胜


    分析

    首先是一个重要的性质:双方必然有一方永远无法吃掉另一方

    考虑象棋的移动,每次((xpm 1,ypm 2))或者((xpm 2,ypm 1))

    每次操作,必然导致(x+ymod 2)改变,在双方轮流操作的过程中

    必然有一方走的时候永远无法和另一方同奇偶,也就是无法吃掉另一方


    在此基础上,考虑几种情况

    (D(a,b))(a,b)两点的距离,(f)为先手是否永远不会被吃

    1.先手可以在不被后手吃掉的情况下到达目标,且先于后手

    先于后手即(D(S_1,T_1)leq D(S_2,T_2))

    先手不被后手吃掉的情况

    1.(f) : 显然

    2.(D(S_1,T_1)<D(S_2,T_1))

    此时,假设后手存在一个吃掉先手的策略

    那么后手经过这个吃掉先手的点到达(T_1)的最短路一定和先手相同,故矛盾


    2.后手可以在不被先手吃掉的情况下到达目标,且先于先手

    (D(S_1,T_1)>D(S_2,T_2))

    对称情况

    1.(not f)

    2.(D(S_2,T_2)<D(S_1,T_2)-1)

    以上两种情况均直接冲最短路到达目标


    3.双方均无法安全直接抵达目标

    此时,考虑选择不会被吃的一方操作

    由于自己是无敌的,可以考虑先猛扑对方的终点

    3.1 (f=true),选择先手

    先走到(T_2)堵住后手,然后可以绕三步到达(T_1)

    先手占据(T_2)时,后手无法到达(T_2)

    走第一步时,由于先手限制着,后手无法进入(T_2)

    走第二步时,根据奇偶性分析,后手无法到达(T_2)的奇偶性

    第三步到达目标

    3.2(f=false),同理

    实现

    可以好好封装一下

    我曾经以为不用读入

    由于交互器下面读入的参数可能会让交互器走智障操作

    如果能吃掉对方,一定要直接吃掉

    const int N=1010,INF=1e9+10;
    const int dx[]={1,1,-1,-1,2,2,-2,-2};
    const int dy[]={2,-2,2,-2,1,-1,1,-1};
    
    int n,m,opt;
    int x=-2,y=-2;
    void input(){ 
    	x=rd(),y=rd(); 
    	if(x==-1) exit(0);
    }
    void CB(){ puts("BLACK"),fflush(stdout),input(); }
    void CW(){ puts("WHITE"),fflush(stdout); }
    
    struct Bfser{
    	int dis[N][N],pre[N][N];
    	int QX[N*N],QY[N*N],L,R;
    	int u,v;
    	int Reach() {
    		int a=abs(u-x),b=abs(y-v);
    		if(a>b) swap(a,b);
    		return a==1 && b==2;
    	}
    	void Bfs(int x,int y){
    		u=x,v=y;
    		QX[L=R=1]=x,QY[1]=y,pre[x][y]=-1,dis[x][y]=1;
    		for(;L<=R;) {
    			x=QX[L],y=QY[L++];
    			rep(i,0,7) {
    				int x1=x+dx[i],y1=y+dy[i];
    				if(x1<1 || y1<1 || x1>n || y1>m || dis[x1][y1]) continue;
    				dis[x1][y1]=dis[x][y]+1,QX[++R]=x1,QY[R]=y1,pre[x1][y1]=i;
    			}
    		}
    	}
    	void Go(int d,int k=1) {
    		if(Reach()) printf("%d %d
    ",x,y),fflush(stdout),exit(0);
    		printf("%d %d
    ",u+=dx[d],v+=dy[d]),fflush(stdout);
    		if(k) input();
    	}
    	void Go(int x,int y,int k) {
    		vector <int> s;
    		while(~pre[x][y]) {
    			int t=pre[x][y];
    			s.pb(t),x-=dx[t],y-=dy[t];
    		}
    		drep(i,s.size()-1,0) Go(s[i],k+i);
    	}
    } B,W;
    
    int main(){
    	n=rd(),m=rd();
    	int x1=rd(),y1=rd(),x2=rd(),y2=rd();
    	W.Bfs(x1,y1),B.Bfs(x2,y2);
    	int f=((x1+y1)&1)!=((x2+y2)&1);
    	if(W.dis[n/2][m/2]<=B.dis[n/2+1][m/2] && (f || W.dis[n/2][m/2]<B.dis[n/2][m/2])) {
    		CW(),x=x2,y=y2,W.Go(n/2,m/2,0);
    	} else if(B.dis[n/2+1][m/2]<W.dis[n/2][m/2] && (B.dis[n/2+1][m/2]<W.dis[n/2+1][m/2]-1 || !f)) {
    		CB(),B.Go(n/2+1,m/2,0);
    	} else if(f) {
    		CW(),x=x2,y=y2,W.Go(n/2+1,m/2,1);
    		W.Go(2),W.Go(5),W.Go(7,0);
    	} else {
    		CB(),B.Go(n/2,m/2,1);
    		B.Go(0),B.Go(7),B.Go(5,0);
    	}
    }
    
  • 相关阅读:
    LeetCode Power of Three
    LeetCode Nim Game
    LeetCode,ugly number
    LeetCode Binary Tree Paths
    LeetCode Word Pattern
    LeetCode Bulls and Cows
    LeeCode Odd Even Linked List
    LeetCode twoSum
    549. Binary Tree Longest Consecutive Sequence II
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14744488.html
Copyright © 2011-2022 走看看