ZOJ 3780 Paint the Grid Again-贪心模拟/拓扑排序

http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3780

给你一个n*m的 OX矩阵

要求你通过两个操作,对一个初始化为空白的矩阵操作,得到目标矩阵

要求step最小且操作序列的字典序最小。

操作分别是:

1:RX 把X行涂为X

2:CY 把y列涂为O


要还原的话,我们可以从最后一步推起。

 要字典序最小,我们就需要逆向构图,每次找最大的,因此每次优先选行,行不能选了再选列


预处理 vis_row【】 ,vis_col[]

每次要涂上一行的话,该行必定全为X,同理该列全为O,

因此vis_row表示该行有多少个O,当vis_row[i]=0,表示该行可以被选【涂一行】


因此预处理后,每次on找一遍行,找到该行后,for一遍该行所有数,去更新每一列的 vis_col【】

当行无法被选了,则选列,用一个变量记录被涂色的格子个数,当全部无法再涂,结束循环。

如果全部格子被涂了,则输出方案,否则输出no sulotion

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<stack>
using namespace std;

char M[505][505];

int ro[505],cx[505];
struct node
{
    char c;
    int id;
    node(){}
    node(char a,int b){c=a,id=b;}
};
stack<node>ans;

int main()
{
    //freopen("xl_in.txt","r",stdin);
    int t;
    cin>>t;
    while(t--)
    {
        while(!ans.empty())
            ans.pop();

         int n;
   scanf("%d",&n);
   getchar();
   for(int i=0;i<n;i++)
        cin>>M[i];

    for(int i=0;i<n;i++)
    {
        int cnt=0;
          for(int j=0;j<n;j++)
            if(M[i][j]=='O')
                cnt++;

        ro[i]=cnt;

    }

    for(int i=0;i<n;i++)
    {
        int cnt=0;
          for(int j=0;j<n;j++)
            if(M[j][i]=='X')
                cnt++;

        cx[i]=cnt;

    }
int mm=n*n;
    while(mm)
    {

         bool ok=false;

           for(int i=n-1;i>=0;i--)
            {
                if(ro[i]==0)
                {
                    for(int j=0;j<n;j++)
                        if(M[i][j]=='X')
                        cx[j]--;

                    for(int j=0;j<n;j++)
                       {
                           if(M[i][j]!=' ') mm--;
                           M[i][j]=' ';
                       }
                     ans.push(node('R',i));
                    ok=true;
                    ro[i]=99999999;
                    break;
                }
            }

            if(ok)
                continue;

            for(int i=n-1;i>=0;i--)
            {
                if(cx[i]==0)
                {
                    for(int j=0;j<n;j++)
                        if(M[j][i]=='O')
                        ro[j]--;

                    for(int j=0;j<n;j++)
                       {

                           if(M[j][i]!=' ') mm--;
                            M[j][i]=' ';
                       }

                     ans.push(node('C',i));

                    ok=true;

                    cx[i]=99999999;
                    break;
                }
            }

            if(!ok)
                break;

    }


        if(mm)
            printf("No solution\n");
        else
        {
            int st=1;
            while(!ans.empty())
            {

                node tmp=ans.top();
                ans.pop();
                if (!st)
                    cout<<" "<<tmp.c<<tmp.id+1;
                else
                    cout<<tmp.c<<tmp.id+1;

                st=0;


            }

            cout<<endl;

        }


    }





    return 0;
}


你可能感兴趣的:(ZOJ 3780 Paint the Grid Again-贪心模拟/拓扑排序)