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

来源:互联网 发布:飞常准软件怎么样 编辑:程序博客网 时间:2024/06/06 01:55

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;}


0 0