• [CF 294D]Shaass and Painter Robot解题报告


    题意

    有一个n*m的网格,有一个机器人初始在(x,y),面朝某个斜45°的方向。机器人会一直走,遇到墙就按弹性碰撞规则(就像台球碰到桌子边缘一样)反弹。机器人每走一格,就会将其所在格子染黑。问机器人走几格之后会将整张网格染成黑白相间(或判断这种情况永远不会发生)。

    分析

    首先有一个结论:边缘上所有该染黑的格子都已染黑,当且仅当整张网格已按要求染成黑白相间。

    证法是归纳。假设第一行该染黑的格子都已染黑,那就会发现第二行该染黑的格子都已染黑。因为第一行某个染黑格必定一进一出,即其左下和右下的两格都染黑了。当然也要考虑角上的情况,还有第一行该染黑的最后一个格子只进不出的情况(这时由于它两旁相间的格子都已染黑,所以左下和右下的两格必定也染黑)。故用数学归纳法可证。

    那么问题就很简单了:开一个map,储存所有已访问过的边缘格子。然后模拟机器人的行走。将机器人的速度分解成水平和竖直两个分量,这个想法是很优美的。

    对n,m的奇偶性讨论之后会发现,边缘上该染黑的格子永远有n+m-2个。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int INF=0x7fffffff/2;
    map<int,int> A[100010];
    int n,m,now,dx,dy,x,y;
    char ch[10];
    void work(void){
    	scanf("%d%d",&n,&m);
    	scanf("%d%d",&x,&y);
    	scanf("%s",ch+1);
    	if(ch[1]=='U') dx=-1;
    	else dx=1;
    	if(ch[2]=='L') dy=-1;
    	else dy=1;
    	int rem=n+m-2;
    	if(x==1||x==n||y==1||y==m){
    		A[x][y]=1;
    		rem--;
    	}
    	int timer=0;
    	LL ans=1;
    	while(true){
    		timer++;
    		if(timer>=500000){
    			cout<<-1<<endl;
    			return;
    		}
    		int dis=INF;
    		if(dx==1) dis=min(dis,n-x);
    		else dis=min(dis,x-1);
    		if(dy==1) dis=min(dis,m-y);
    		else dis=min(dis,y-1);
    		x+=dx*dis,y+=dy*dis;
    		ans+=dis;
    		if(x==1) dx=1;
    		else if(x==n) dx=-1;
    		if(y==1) dy=1;
    		else if(y==m) dy=-1;
    		if(A[x][y]==0){
    			rem--;
    			A[x][y]=1;
    		}
    		if(!rem){
    			cout<<ans<<endl;
    			return;
    		}
    	}
    }
    int main(){
    	work();
    	return 0;
    }
    


  • 相关阅读:
    enum
    高可用复用类
    int 和 Integer 的区别
    MysqlMd5加密
    软件测试例子
    Wordcount
    大气登录页面
    生成二维码的JAVA
    多态的理解
    打印低头思故乡 java
  • 原文地址:https://www.cnblogs.com/wmdcstdio/p/7554240.html
Copyright © 2020-2023  润新知