ZOJ3780 Paint the Grid Again(模拟)

描述

Leo has a grid with N × N cells. He wants to paint each cell with a
specific color (either black or white).

Leo has a magical brush which can paint any row with black color, or
any column with white color. Each time he uses the brush, the previous
color of cells will be covered by the new color. Since the magic of
the brush is limited, each row and each column can only be painted at
most once. The cells were painted in some other color (neither black
nor white) initially.

Please write a program to find out the way to paint the grid.

Input

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

The first line contains an integer N (1 <= N <= 500). Then N lines
follow. Each line contains a string with N characters. Each character
is either ‘X’ (black) or ‘O’ (white) indicates the color of the cells
should be painted to, after Leo finished his painting.

Output

For each test case, output “No solution” if it is impossible to find a
way to paint the grid.

Otherwise, output the solution with minimum number of painting
operations. Each operation is either “R#” (paint in a row) or “C#”
(paint in a column), “#” is the index (1-based) of the row/column. Use
exactly one space to separate each operation.

Among all possible solutions, you should choose the lexicographically
smallest one. A solution X is lexicographically smaller than Y if
there exists an integer k, the first k - 1 operations of X and Y are
the same. The k-th operation of X is smaller than the k-th in Y. The
operation in a column is always smaller than the operation in a row.
If two operations have the same type, the one with smaller index of
row/column is the lexicographically smaller one.

Sample Input

2
2
XX
OX
2
XO
OX

Sample Output

R2 C1 R1
No solution

思路

首先说题意,有一个n*n的矩阵本来是空的,一个人人有一把神奇的刷子,可以把某一列的方格刷成O,可以把某一行的格子刷成X,现在给出一个图,这是刷了若干次刷子以后的图,问如何从空方格刷成现在的局面,如果不能达到,输出No solution,如果可以就输出路径。输出路径的时候如果有多种方式可以到达,按照字典序输出。先输出行,再输出列,输出的时候都是从小到大。

可以根据最后给的图考虑,如果可以刷的话,那么必定有一列或者一行是相同的,因为输出是按照字典序输出所以倒着来的时候先找列最大的,再找行最大的。当把某一行或列倒着找的时候就把这一行或列变成#,当不能刷的时候判断图中是否还有没有刷完的块,如果有就输出No solution

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include<list>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=500+50;
char s[N][N];
int n;
stack<string>st;
string get_s(int x)
{
    stringstream ss;
    string str;
    ss<<x;
    ss>>str;
    return str;
}
int get_num()
{
    while(1)
    {
        //行
        int r=0,c=0,flag=0;//flag标记图中是否还有字符
        for(int i=n; i>=1; i--)
        {
            int f1=1,f2=0;//f1标记是否出现'O',f2标记是否出现'X'
            for(int j=1; j<=n; j++)
            {
                if(s[i][j]!='#')flag=1;
                if(s[i][j]=='X')f2=1;
                if(s[i][j]=='O')
                {
                    f1=0;
                    break;
                }
            }
            if(f1&&f2)
            {
                r=i;
                break;
            }
        }
        //列
        for(int i=n; i>=1; i--)
        {
            int f1=1,f2=0;//f1标记是否出现'X',f2标记是否出现'O'
            for(int j=1; j<=n; j++)
            {
                if(s[j][i]!='#')flag=1;
                if(s[j][i]=='O')f2=1;
                if(s[j][i]=='X')
                {
                    f1=0;
                    break;
                }
            }
            if(f1&&f2)
            {
                c=i;
                break;
            }
        }
        if(c>0)//可以找到较大的列
        {
            string res="C"+get_s(c);
            st.push(res);
            for(int i=1; i<=n; i++)s[i][c]='#';
        }
        else if(r>0)//可以找到较大的行
        {
            string res="R"+get_s(r);
            st.push(res);
            for(int i=1; i<=n; i++)s[r][i]='#';
        }
        else//r==0&c==0
        {
            if(flag)
                return 0;
            return 1;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        while(!st.empty())st.pop();
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%s",s[i]+1);
        if(get_num()==0)
            puts("No solution");
        else
        {
            while(st.size()>1)
            {
                cout<<st.top()<<" ";
                st.pop();
            }
            cout<<st.top()<<endl;
        }
    }
    return 0;
}
/*
2
4
OOOO
XXXX
OOXX
XOXX
*/

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/80068473