ZOJ 4093 浙大校赛D题 Robot Cleaner II(思维+构造题)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4093

题意:题意基于ZOJ4092题意的基础上,给一个12*12的矩阵,矩阵中值为1的即这个点是墙,为0即为空地,为2即为空地上有一个垃圾。现在有6种操作,'U','D','L','R',表示向上下左右四个方向移动一步,如果下一步是墙就留在原地,'I'是停留原地,'P'表示捡起地上的垃圾,若地上无垃圾则不做操作,一个地方如果本来有垃圾后被拿走,那么值由2变到0,现在有一个长度为243的指令序列,若当前处于(i,j)位置上,那么定义x = 81*m[i][j]+27*m[i-1][j]+9*m[i+1][j]+3*m[i][j-1]+1*m[i][j+1],然后取指令序列的第x+1个指令进行操作。题目没有输入,后台数据会给出1000个这样的矩阵,保证只有周围一圈是墙,里面10*10的矩阵都是0或2,且各50个,随机等概率分布,现在题目要求一个长为243的指令序列,使得这一千个矩阵(人走的起点均为(2,2))中各走两百步之后所能捡到的垃圾数不小于原垃圾总数的95%

思路:首先,可以发现‘I’这个指令啥用没有,然后发现可以从1~243遍历这个指令序列,每一个序号只对应一种情况,比如3号指令,一定对应当前位为0,上下左均为0,右边为2的情况(如下图)这样一个位置(对81取模,再对27取模...得到)

 0 
002
 0 

那么可以得出第i个指令的规律:

        1.i/81 == 1时,该种情况不可能出现,指令任意即可

        2.i/81 == 2时,当前有垃圾,一定是先捡垃圾更优,所以指令为‘P’

        3.i/81==0时,再进行分类:

              若该情况是四个方向上有1的,那么即是沿着墙的,先暂定(10*10)沿墙顺时针走,在此基础上,若沿墙走的点周围有                垃圾,先往有垃圾的方向走。

              若位置周围全都是空地,那么就默认往右走

              若位置周围超过一个地方有垃圾,那么方向的选择顺序为上右左下

代码:

#include<iostream>
#include <cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<functional>
#include <unordered_map>
#include<queue>
#include<cmath>
#include<unordered_map>
#include<fstream>
#include<ctime>
using namespace std;

typedef long long ll;
const ll mod = 1e9 + 7;

char s[500];
int n = 12;

int main()
{
	memset(s, 0, sizeof(0));
	for (int i = 1; i <= 243; i++)
	{
		s[i] = 'P';
	}
	for (int j = 1; j <= 243; j++)
	{
		int k[5];
		int i = j;
		memset(k, 0, sizeof(k));
		if (i / 81)continue;
		if (i/27)//上
		{
			if (i / 27 == 2)
			{
				s[j] = 'U';
				continue;
			}
			else
				k[0] = 1;
		}
		i = j % 3;//右
		if (i == 2)
		{
			s[j] = 'R';
			continue;
		}
		if (i == 1)
			k[3] = 1;
		
		i = j%9;//左
		if (i / 3)
		{
			if (i / 3 == 2)
			{
				s[j] = 'L';
				continue;
			}
			else
				k[2] = 1;
		}
		i = j % 27;//下
		if (i / 9)
		{
			if (i / 9 == 2)
			{
				s[j] = 'D';
				continue;
			}
			else
				k[1] = 1;
		}
		if (k[0] && k[1])
		{
			s[j] = 'R';
		}
		else if(k[2] && k[1])
		{
			s[j] = 'U';
		}
		else if(k[0] && k[3])
		{
			s[j] = 'D';
		}
		else if (k[1] && k[3])
		{
			s[j] = 'L';
		}
		else if (k[0])
		{
			s[j] = 'R';
		}
		else if (k[3])
		{
			s[j] = 'D';
		}
		else if (k[1])
		{
			s[j] = 'L';
		}
		else if (k[2])
		{
			s[j] = 'U';
		}
		else
		{
			s[i] = 'R';
		}
	}
	s[244] = '\0';
	for (int i = 243; i > 1; i--)
		s[i] = s[i - 1];
	s[1] = 'R';
	printf("%s\n", s + 1);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值