2020ICPC南京 Evil Coordinate(几何,模拟,构造)

链接

题目描述

A robot is standing on an infinite 2-dimensional plane. Programmed with a string s 1 s 2 ⋯ s n s_1s_2\cdots s_n s1s2sn of length n n n, where s i ∈ { ’U’ , ’D’ , ’L’ , ’R’ } s_i \in \{\text{'U'}, \text{'D'}, \text{'L'}, \text{'R'}\} si{’U’,’D’,’L’,’R’}, the robot will start moving from ( 0 , 0 ) (0, 0) (0,0) and will follow the instructions represented by the characters in the string.

More formally, let ( x , y ) (x, y) (x,y) be the current coordinate of the robot. Starting from ( 0 , 0 ) (0, 0) (0,0), the robot repeats the following procedure n n n times. During the i i i-th time:
If s i = ’U’ s_i = \text{'U'} si=’U’ the robot moves from ( x , y ) (x, y) (x,y) to ( x , y + 1 ) (x, y+1) (x,y+1);
If s i = ’D’ s_i = \text{'D'} si=’D’ the robot moves from ( x , y ) (x, y) (x,y) to ( x , y − 1 ) (x, y-1) (x,y1);
If s i = ’L’ s_i = \text{'L'} si=’L’ the robot moves from ( x , y ) (x, y) (x,y) to ( x − 1 , y ) (x-1, y) (x1,y);
If s i = ’R’ s_i = \text{'R'} si=’R’ the robot moves from ( x , y ) (x, y) (x,y) to ( x + 1 , y ) (x+1, y) (x+1,y).

However, there is a mine buried under the coordinate ( m x , m y ) (m_x, m_y) (mx,my). If the robot steps onto ( m x , m y ) (m_x, m_y) (mx,my) during its movement, it will be blown up into pieces. Poor robot!

Your task is to rearrange the characters in the string in any order, so that the robot will not step onto ( m x , m y ) (m_x, m_y) (mx,my).

输入描述:

There are multiple test cases. The first line of the input contains an integer T T T indicating the number of test cases. For each test case:

The first line contains two integers m x m_x mx and m y m_y my ( − 1 0 9 ≤ m x , m y ≤ 1 0 9 ) (-10^9 \le m_x, m_y \le 10^9) (109mx,my109) indicating the coordinate of the mine.

The second line contains a string s 1 s 2 ⋯ s n s_1s_2\cdots s_n s1s2sn of length n n n ( 1 ≤ n ≤ 1 0 5 , s i ∈ { ’U’ , ’D’ , ’L’ , ’R’ } ) (1 \le n \le 10^5 , s_i \in \{\text{'U'}, \text{'D'}, \text{'L'}, \text{'R'}\}) (1n105,si{’U’,’D’,’L’,’R’}) indicating the string programmed into the robot.

It’s guaranteed that the sum of n n n of all test cases will not exceed 1 0 6 10^6 106.

输出描述:

For each test case output one line. If a valid answer exists print the rearranged string, otherwise print “Impossible” (without quotes) instead. If there are multiple valid answers you can print any of them.

输入

5
1 1
RURULLD
0 5
UUU
0 3
UUU
0 2
UUU
0 0
UUU

输出

LDLRUUR
UUU
Impossible
Impossible
Impossible

思路

刚开始想的是能不能深搜一下,因为只有一个点不能走,回溯一下就避开了。但是后来发现了这样的数据:

90000 1
URRR...RRR //(length=100000)

如果优先搜索 ‘U’ ,再搜 ‘R’ 的话,第一次搜索路径为 “URRR…RRR” ,踩到雷了。回溯无数次,第二次搜的路径为 “RUR…RRR” ,同样踩到雷。

这样的复杂度,不出意外的话是要出意外的。

然后就想着,能不能一次搜索同一个方向的若干步,不要一步一步地搜。举了几个例子后,发现这样的一个结论:

如果存在一条路径,可以不踩地雷走到终点。那么也存在着 “每个方向只走一次” 的路径,同样能不踩地雷到达终点。

然后就可以优化深搜了,只搜方向。搜索树最大深度为 4 4 4,大大降低复杂度。

也有人是用全排列做的,同样是基于上面这个结论,其实和深搜也没什么区别。

bool check(int dir); 函数判断从 { n x , n y } \{nx,ny\} {nx,ny} d i r dir dir 方向走(有多少步走多少步)会不会踩到地雷。

void walk(int dir,int stat); 函数修改当前位置 { n x , n y } \{nx,ny\} {nx,ny} d i r dir dir 方向走,并且记录路径。当 s t a t stat stat − 1 -1 1 时,原路返回,删掉行走路径。

#include<bits/stdc++.h>
using namespace std;
string s; int x,y,T,mp[128],rmp[5],op[5],path[5][2],tot,nx,ny,allDir;

bool check(int dir){
	if(dir==1) return !(nx==x&&1LL*(y-ny)*(y-(ny+op[dir]))<=0);
	else if(dir==2) return !(nx==x&&1LL*(y-ny)*(y-(ny-op[dir]))<=0);
	else if(dir==3) return !(ny==y&&1LL*(x-nx)*(x-(nx-op[dir]))<=0);
	else return !(ny==y&&1LL*(x-nx)*(x-(nx+op[dir]))<=0);
} 

void walk(int dir,int stat){
	if(dir==1) ny+=stat*op[dir];
	else if(dir==2) ny-=stat*op[dir];
	else if(dir==3) nx-=stat*op[dir];
	else nx+=stat*op[dir];
	if(stat==1) path[++tot][0]=dir,path[tot][1]=op[dir];
	else --tot;
}

bool dfs(int p){
	if(p>=allDir) return true;
	for(int i=1;i<=4;i++)
		if(op[i]>0&&check(i)){
			walk(i,1);  int t=op[i]; op[i]=0;
			if(dfs(p+1)) return true;
			op[i]=t; walk(i,-1);
		}
	return false;
}

void out(){
	for(int i=1;i<=tot;i++)
		for(int j=1;j<=path[i][1];j++)
			cout<<(char)rmp[path[i][0]];
	cout<<"\n";
}

void solve(){
	nx=ny=tot=allDir=0;
	memset(op,0,sizeof(op));
	cin>>x>>y>>s;
	for(int i=0;i<(int)s.size();i++) op[mp[(int)s[i]]]++;
	for(int i=1;i<=4;i++) allDir+=op[i]>0;
	if(dfs(0)) out();
	else cout<<"Impossible\n";
}

int main(){
	mp['U']=1; mp['D']=2; mp['L']=3; mp['R']=4;
	rmp[1]='U'; rmp[2]='D'; rmp[3]='L'; rmp[4]='R';
	ios::sync_with_stdio(false);
	for(cin>>T;T;T--) solve();
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_51864047

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值