Paint the Grid Again

来源:互联网 发布:fifa online3改键软件 编辑:程序博客网 时间:2024/06/16 18:53

题目链接

  • 题意:
    对于一个空的矩阵,每次有两种操作:1.使一整行变成‘X'  2.使一整列变成’O'   且每行每列至多操作一次
    给定n*n(1<=n<=500)的目标矩阵,输出操作序列(字典序最小)使得对于一个空矩阵经过次操作过后可以变成目标矩阵
  • 分析:
    对于m[x][y],既然每行每列最多只能操作一次,那么,其实每个点都给出了一个对于这个行列的一个操作顺序。如果是‘X',那么必然先列后行,如果是’O',则是先行后列。我们就可以想到,给定一些部分序关系,构造一个全序关系满足这个部分序关系,也就是拓扑排序。
    需要注意一点,处理一下某些不需要操作的行列

    这种题目也有点像构造法,给出一个序列满足题意即可,所以题目要求字典序最小。如果还没有想到是用拓扑排序,直接考虑字典序最小其实不怎么好做。。。正是因为拓扑排序答案的不确定性,加上字典序限制是很正常的。所以,以后见到字典序最小可以考虑一下是不是拓扑排序
  • 关键:
    考虑到每一个数组元素,得到一个部分序关系,输出一个全序关系

const int MAXV = 1100;struct Graph{    int n;    vector<int> G[MAXV];    int in[MAXV];    void init(int n)    {        this->n = n;        REP(i, n)        {            G[i].clear();            in[i] = 0;        }    }    void add(int a, int b)    {        G[a].push_back(b);        in[b]++;    }    bool solve(vector<int>& ans)    {        priority_queue<int, vector<int>, greater<int> > q;        REP(i, n) if (in[i] == 0) q.push(i);        while (!q.empty())        {            int u = q.top(); q.pop();            ans.push_back(u);            REP(i, G[u].size())            {                int v = G[u][i];                if (--in[v] == 0) q.push(v);            }        }        REP(i, n) if (in[i] > 0)            return false;        return true;    }} tt;char m[MAXV][MAXV];bool mark[MAXV];int main(){//    freopen("in.txt", "r", stdin);    int T, n;    RI(T);    REP(kase, T)    {        RI(n);        CLR(mark, true);        tt.init(2 * n);        getchar();        REP(i, n) gets(m[i]);        REP(i, n)        {            int cnt1 = 0, cnt2 = 0;            REP(j, n)            {                if (m[i][j] == 'O')                {                    cnt1++;                    tt.add(i, n + j);                }                if (m[j][i] == 'X')                {                    cnt2++;                    tt.add(n + i, j);                }            }            if (cnt1 == n) mark[i] = false;            if (cnt2 == n) mark[i + n] = false;        }        vector<int> ans;        if (!tt.solve(ans))        {            puts("No solution");            continue;        }        int cnt = 0;        REP(i, ans.size())        {            if (cnt) putchar(' ');            if (!mark[ans[i]]) continue;            cnt++;            if (ans[i] >= n)                printf("C%d", ans[i] - n + 1);            else                printf("R%d", ans[i] + 1);        }        puts("");    }    return 0;}


4 0
原创粉丝点击