https://ac.nowcoder.com/acm/contest/21739/E
- 这题有更简单的做法(枚举UDLR全排列),我用这个分类讨论的方法折腾了2个半小时才终于AC…
思路:
-
1.首先我们可以想到,给定了一个走法的序列,不管这个序列的排列是怎样,它的终点一定确定了.所以炸弹(mx,my)如果在起点(0,0)或终点(x,y)那结果肯定是 I m p o s s i b l e Impossible Impossible.
-
2.还有一种 I m p o s s i b l e Impossible Impossible的情况就是当X轴方向没有步数( C n t R = 0 & & C n t L = 0 Cnt_R=0\&\& Cnt_L=0 CntR=0&&CntL=0)且炸弹在Y轴方向的必经之路上;当Y轴方向没有步数( C n t U = 0 & & C n t D = 0 Cnt_U=0\&\& Cnt_D=0 CntU=0&&CntD=0)且炸弹在X轴方向的必经之路上.
-
3.除去上面两种,剩余情况都是总能找到一个序列使机器人不经过炸弹的. 我们可以分情况讨论:
-
a.终点不在坐标轴上
我们将路径简化为两种,先横着走再后竖着走和先竖着走再横着走.
这种情况比较简单,只需要判断炸弹是否在任意一条路径上,那么不走这条路径即可.例如:若炸弹在1上,那就走2;若炸弹在2上或者炸弹在其他地方,那就走1.
-
b.终点在坐标轴上
这种情况看似简单,实则比较复杂.例如:终点在Y轴上,那说明L和R的步数相等.但先L或先R可能会对答案造成影响,所以我们要进行一些判断.例如:炸弹若在X轴下方,那么我们先U后D肯定不会有问题;炸弹若在Y轴左方,那先R和L肯定不会有问题.(会有问题的我们已经在第二种impossible中筛掉了).这里语言描述起来会比较麻烦,直接看代码应该会比较好理解.
-
-
4.最后要注意一下正负号的问题,然后把每种情况交代清楚,应该就能AC了.
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<unordered_map>
#include<set>
//#pragma GCC optimize(2)
//#pragma GCC optimize("inline")
//#pragma GCC optimize("-fgcse")
//#pragma GCC target("avx","sse2")
//#pragma GCC optimize("-fgcse-lm")
//#pragma GCC optimize("-fipa-sra")
//#pragma GCC optimize("-ftree-pre")
//#pragma GCC optimize("-ftree-vrp")
//#pragma GCC optimize("-fpeephole2")
//#pragma GCC optimize("-ffast-math")
//#pragma GCC optimize("-fsched-spec")
//#pragma GCC optimize("unroll-loops")
using namespace std;
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PIII pair<int,PII>
#define PLLL pair<ll,PLL>
#define fi first
#define se second
#define pb push_back
#define debug(a) cout << #a << " " << a << '\n';
const int N = 1e5 + 5;
const int M = 1e5 + 5;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
ll mx, my;
bool tong(ll x, ll y) {//判断两个数是否同号
if (x == 0 || y == 0)return true;
if (x >= 0 && y >= 0)return true;
if (x <= 0 && y <= 0)return true;
return false;
}
void solve() {
map<char, ll> mp;
cin >> mx >> my;
string path;
cin >> path;
int len = path.length();
for (int i = 0; i < len; i++) {
if (path[i] == 'L')mp['L']++;
else if (path[i] == 'R')mp['R']++;
else if (path[i] == 'U')mp['U']++;
else if (path[i] == 'D')mp['D']++;
}
ll x = mp['R'] - mp['L'];//计算终点(一定会到达)
ll y = mp['U'] - mp['D'];
//炸弹的位置在终点或起点
if ((mx == x && my == y) || (mx == 0 && my == 0)) {
cout << "Impossible\n";
}
//只能在Y轴移动,炸弹在必经之路上
else if ((!mp['L'] && !mp['R']) && (tong(my, y) && abs(my) <= abs(y) && mx == 0)) {
cout << "Impossible\n";
}
//只能在X轴移动,炸弹在必经之路上
else if ((!mp['U'] && !mp['D']) && (tong(mx, x) && abs(mx) <= abs(x) && my == 0)) {
cout << "Impossible\n";
}
else {
//L和R最终抵消了
if (x == 0) {
string ans;
if (mx > 0) {//炸弹在Y轴右侧,那么就先走左面
for (int i = 0; i < mp['L']; i++) ans += 'L';
if (my < 0) {
//炸弹在X轴下侧,那么就先走上面
for (int i = 0; i < mp['U']; i++) ans += 'U';
for (int i = 0; i < mp['D']; i++) ans += 'D';
}
else {
for (int i = 0; i < mp['D']; i++) ans += 'D';
for (int i = 0; i < mp['U']; i++) ans += 'U';
}
for (int i = 0; i < mp['R']; i++) ans += 'R';
}
else {
for (int i = 0; i < mp['R']; i++) ans += 'R';
if (my < 0) {
for (int i = 0; i < mp['U']; i++) ans += 'U';
for (int i = 0; i < mp['D']; i++) ans += 'D';
}
else {
for (int i = 0; i < mp['D']; i++) ans += 'D';
for (int i = 0; i < mp['U']; i++) ans += 'U';
}
for (int i = 0; i < mp['L']; i++) ans += 'L';
}
cout << ans << '\n';
return;
}
//U和D最终抵消了
if (y == 0) {
string ans;
if (my > 0) {
//炸弹在X轴上侧,那么就先走下面
for (int i = 0; i < mp['D']; i++) ans += 'D';
if (mx < 0) {//炸弹在Y轴左侧,那么就先走右面
for (int i = 0; i < mp['R']; i++) ans += 'R';
for (int i = 0; i < mp['L']; i++) ans += 'L';
}
else {
for (int i = 0; i < mp['L']; i++) ans += 'L';
for (int i = 0; i < mp['R']; i++) ans += 'R';
}
for (int i = 0; i < mp['U']; i++) ans += 'U';
}
else {
for (int i = 0; i < mp['U']; i++) ans += 'U';
if (mx < 0) {
for (int i = 0; i < mp['R']; i++) ans += 'R';
for (int i = 0; i < mp['L']; i++) ans += 'L';
}
else {
for (int i = 0; i < mp['L']; i++) ans += 'L';
for (int i = 0; i < mp['R']; i++) ans += 'R';
}
for (int i = 0; i < mp['D']; i++) ans += 'D';
}
cout << ans << '\n';
return;
}
//终点不在坐标轴上,可以通过先横后竖或者先竖后横的方法走
if ((my == 0 || mx == x)) {//如果炸弹不在先横后竖的走法上,那就走先竖后横
string ans;
for (int i = 0; i < mp['U']; i++) ans += 'U';
for (int i = 0; i < mp['D']; i++) ans += 'D';
for (int i = 0; i < mp['L']; i++) ans += 'L';
for (int i = 0; i < mp['R']; i++) ans += 'R';
cout << ans << '\n';
}
else {
string ans;
for (int i = 0; i < mp['L']; i++) ans += 'L';
for (int i = 0; i < mp['R']; i++) ans += 'R';
for (int i = 0; i < mp['U']; i++) ans += 'U';
for (int i = 0; i < mp['D']; i++) ans += 'D';
cout << ans << '\n';
}
}
}
int main() {
ios::sync_with_stdio(false);
#ifdef LOCAL
int begin_time = clock();
freopen("../input.txt", "r", stdin);
// freopen("../output.txt", "w", stdout);
#endif
int T = 1;
cin >> T;
for (int cas = 1; cas <= T; cas++) {
#ifdef LOCAL
printf("Case #%d: ", cas);
#endif
solve();
}
#ifdef LOCAL
int end_time = clock();
printf("\nRun time: %.2lf ms", (double) (end_time - begin_time) / CLOCKS_PER_SEC * 1000);
#endif
return 0;
}