为了纪念这道题,我决定贴一个特别迷的AC代码上来,纪念我那估计二十来发WA和TLE。如果有人发现我的问题了,欢迎回复或者私信,感激不尽
链接:http://codeforces.com/gym/100971/problem/J
首先这道题的意思就是, 给一个地图,#表示障碍,.表示可以走,1表示1号机器人的位置,2表示2号机器人的位置,现在想交换两个人的位置,问能否做到,
两个限制条件就是,1:在同一时刻,他们不能在同一位置,2:如果他们相邻,那他们不能直接交换位置。
然后,我的理解,首先,他没有要求两个人必须同时走,就是有人可以等,那就简单很多了,分两种情况,一种是有T字型路口的,只要两个人之间有道路通过,那么有一个 就可以躲在T字型的一端,然后让另一个人先走,然后它在走,就可以,当然这个T字型路口必须是两个人可以走到的地方。第二种情况就是没有T字型路口,就是每个点周围四个可走的点都<=2,但是有1号的点和2号的点可以连成一个环,就是有回路,然后就肯定一个人从这条路走,一个人从另一条路走,就可以了
想想假如A和B之间只有一条路可走,而且这条路中间没有分叉,B在另一端有个T字型的点,那它可以先跑到T字型的一端躲起来,然后A走过了跑到T字型的另一端躲起来,然后B去A的位置,然后A再去B的位置,就完成交换了。
假如两人本来就相邻的话, 那如果路径数>=2,那也一个人从另一条路走,然后另一个人直接走过来就可以。假如是只能直接过去但是有T字型口的话,比如T字型点在A那里,A可以先躲到T字型的一端,B躲到另一端,A走到B的位置,B走到A的位置,也就完成了
想不出还有什么特殊情况,可能是我对题意理解有错?看他们的程序,好像只判有T字型点或者路径数>=2就行,难道题目保证AB是连通的?
所以,我就只说DFS的写法,在vj上也看到有人BFS写的,没去细看。
DFS,我觉得,
首先,判断嘛,假如路径数>=2,那么要么就是回路,成环,否则的话,肯定有T字型的点,然后就可以了,反正肯定是YES,
否则的话,就是如果(路径数==1,而且在他们可达的地方有T字型的点),就是YES,否则, 就是NO。
但是,这样就一直T,,简直没救了,,附上我的一份我认为对但是一直TLE on 20的代码,而且我感觉,好像没法再优化复杂度了吧,我是用的DFS跑路径数而且遍历所以可达点的,曾试过一次DFS跑路径数,BFS遍历所有点,也TLE on 20了。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
using namespace std;
#define ll long long
#define maxn 400005
const int dx[4] = { 0, 0, 1, -1 };
const int dy[4] = { 1, -1, 0, 0 };
int N, M;
char grid[maxn];
bool walk[maxn];
bool vis[maxn];
bool extra = false;
int ax, ay, bx, by;
int tmp;
int sum = 0;
int xx, yy;
void DFS(int x, int y,bool arrive)
{
if (sum >= 2 || (sum == 1 && extra))
return;
if (extra == false && vis[x*M + y] == false)
{
vis[x*M + y] = true;
tmp = 0;
for (int i = 0; i < 4; ++i)
{
xx = x + dx[i];
yy = y + dy[i];
if (xx >= 0 && xx < N&&yy >= 0 && yy < M&&grid[xx*M + yy] != '#')
{
++tmp;
}
}
if (tmp > 2)
extra = true;
}
if (arrive)
{
for (int i = 0; i < 4; ++i)
{
xx = x + dx[i];
yy = y + dy[i];
if (xx >= 0 && xx < N&&yy >= 0 && yy < M&&grid[xx*M + yy] != '#'&&vis[xx*M + yy] == false)
{
//printf("%d %d\n", xx, yy);
DFS(xx, yy, true);
}
}
}
else
{
bool flag = false;
if (x == bx&&y == by)
{
++sum;
flag = true;
}
walk[x*M + y] = true;
for (int i = 0; i < 4; ++i)
{
xx = x + dx[i];
yy = y + dy[i];
if (xx >= 0 && xx < N&&yy >= 0 && yy < M&&grid[xx*M + yy] != '#'&&walk[xx*M + yy] == false)
{
//printf("%d %d\n", xx, yy);
DFS(xx, yy, flag);
}
}
walk[x*M + y] = false;
}
}
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
scanf("%d%d", &N, &M);
for (int i = 0; i < N; ++i)
{
scanf("%s", &grid[i*M]);
for (int j = 0; j < M; ++j)
{
if (grid[i*M + j] == '1')
{
ax = i; ay = j;
grid[i*M + j] = '.';
}
else if (grid[i*M + j] == '2')
{
bx = i; by = j;
grid[i*M + j] = '.';
}
}
}
DFS(ax, ay,false);
if (sum >= 2 || (sum == 1 && extra))
printf("YES\n");
else
printf("NO\n");
//system("pause");
//while (1);
return 0;
}
我不知道那个20是一组怎样的神数据,反正我把代码中的(sum == 1&&extra)都换成extra之后,就迷之AC了,,而且46ms,快的飞起,难道说只有有T字型的点就可以吗?假如从A出发有T字型的点,但是A和B直接不连通,那怎么做到交换两个人位置呢,被这题干了好久了,,,唉,又读了一遍题,也没发现问题啊。。。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
#define maxn 200005
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
ios_base::sync_with_stdio(NULL);
cin.tie(NULL); cout.tie(NULL);
int N, M;
cin >> N >> M;
int cnt = 0;
bool flag = true;
vector<string> a(N);
for (int i = 0; i < N; ++i)
{
cin >> a[i];
}
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
if (a[i][j] == '#')
continue;
cnt = 0;
if (i != 0 && a[i - 1][j] != '#')
++cnt;
if (i != N - 1 && a[i + 1][j] != '#')
++cnt;
if (j != 0 && a[i][j - 1] != '#')
++cnt;
if (j != M - 1 && a[i][j + 1] != '#')
++cnt;
if (cnt >= 3)
{
cout << "YES" << endl;
return 0;
}
if (cnt == 1)
flag = false;
}
}
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
//system("pause");
//while (1);
return 0;
}