题目链接
题目大意:
需要构造一个n×n的矩阵,每个位置上有一个符号‘U’,‘D’,‘L’,‘R’,‘X’。分别表示上下左右和停止。每个坐标会有一个x,y。假设当前坐标为i,j且上面值为x,y则表示从i,j为起点会在x,y的地方终止。当(x,y)=(-1,-1)表示无法终止,当然要保证在n×n的范围内。
问是否能构造出这样的矩阵,不能就输出“INVALID”。能就输出“VALID”和构造的矩阵。
解题思路:
首先考虑(x,y)=(-1,-1)的情况,这个时候只要指向周围四个点中任意一个为(-1,-1)的点就可以了,因为至少会在两个点之间来回走这也满足无法终止的条件。
然后考虑不是(-1,-1)的情况,直接从终点反过来dfs,每次dfs的下一个点就是终点与当前点相同的点,如果从终点出发走不到当前的点,就是非法的。
解题代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
char mp[maxn][maxn];
struct P{
int x,y;
}a[maxn][maxn];
int mx[]={0,0,-1,1};
int my[]={1,-1,0,0};
char ch[]="RLUD";
char ch1[]="LRDU";
int n;
void dfs(int x,int y)
{
for (int k=0;k<4;k++)
{
int dx=mx[k]+x,dy=my[k]+y;
if (dx<1 || dx>n || dy<1 || dy>n || mp[dx][dy])
continue;
if (a[dx][dy].x==a[x][y].x && a[dx][dy].y==a[x][y].y)
{
mp[dx][dy]=ch1[k];
dfs(dx,dy);
}
}
}
int main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
scanf("%d%d",&a[i][j].x,&a[i][j].y);
}
for(int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
if (a[i][j].x==-1)
{
for (int k=0;k<4;k++)
{
int dx=i+mx[k],dy=j+my[k];
if (dx<1 || dx>n || dy<1 || dy>n)
continue;
if (a[dx][dy].x==-1)
{
mp[i][j]=ch[k];
break;
}
}
}
else
{
//如果终点已经被构造好了 但不是终点则直接非法
if (mp[a[i][j].x][a[i][j].y] && mp[a[i][j].x][a[i][j].y]!='X')
{
cout<<"INVALID";
return 0;
}
//从终点反向dfs
mp[a[i][j].x][a[i][j].y]='X';
dfs(a[i][j].x,a[i][j].y);
}
//当前是(-1,-1)但是周围没有(-1,-1) 或者 从终点出发到不了
if (!mp[i][j])
{
cout<<"INVALID";
return 0;
}
}
}
cout<<"VALID\n";
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
cout<<mp[i][j];
}
cout<<endl;
}
}