题目传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3780
题意:
给一块n*n的格子,每次可以将任意行变成X,或任意列变成O,后操作的将覆盖原先的操作。给出最终图形,要求操作的步骤最少,并按先后顺序输出操作方法(字典序)。
分析:
其实这道题虽然要求操作的步骤最少,但是经过分析可以得知操作的总步骤肯定是一定的。只要按照逆字典序向前模拟删除行和列,最后只要都能删完就说明有解。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 505;
char mp[maxn][maxn];
int n;
bool judge()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(mp[i][j] != '.')
return true;
return false;
}
int ans[maxn*2];
char a[maxn*2];
bool row[maxn], col[maxn];
int main()
{
int T, flag, need;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%s", mp[i]);
int cnt = 0;
memset(row, false, sizeof(row));
memset(col, false, sizeof(col));
while(true)
{
need = flag = 0;
for(int i = n-1; i >= 0; i--)
{
need = 0;
if(row[i+1])
continue;
int j;
for(j = 0; j < n; j++)
{
if(mp[i][j] == 'X')
need = 1;
if(mp[i][j] == 'O')
break;
}
if(j == n && need)
{
flag = 1;
for(j = 0; j < n; j++)
mp[i][j] = '.';
ans[cnt] = i+1;
a[cnt++] = 'R';
row[i+1] = true;
break;
}
}
need = 0;
for(int j = n-1; j >= 0 && flag == 0; j--)
{
need = 0;
int i;
if(col[j+1])
continue;
for(i = 0; i < n; i++)
{
if(mp[i][j] == 'O')
need = 1;
if(mp[i][j] == 'X')
break;
}
if(i == n && need)
{
flag = 1;
for(i = 0; i < n; i++)
mp[i][j] = '.';
ans[cnt] = j+1;
a[cnt++] = 'C';
col[j+1] = true;
break;
}
}
if(flag == 1)
continue;
if(flag == 0 && !judge())
{
flag = 1;
break;
}
else
{
break;
}
}
if(flag)k
{
for(int i = cnt-1; i >= 0; i--)
printf("%c%d%c", a[i], ans[i], i == 0 ? '\n':' ');
}
else
printf("No solution\n");
}
return 0;
}