HDU 5386 Cover

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5386

题目大意:给一个初始矩阵(n×n)、一个目标矩阵(n×n)和m个操作,要求找到一种操作顺序,使初始矩阵变成目标矩阵。操作共有两种,如下:

  L x y: 把当前矩阵第x列的数全变为y
  H x y: 把当前矩阵第x行的数全变为y

输入格式:先输入case数T,每个case第一行是两个整数n和m,接下来n行输入初始矩阵,再下来n行输入目标矩阵。最后m行输入操作。
  1color[i][j]n,color[i][j]为数组元素。
  T=5
  1n100
  1m500

分析:根据数据范围推解题方法,此题对数组元素的大小做了限制,可以从这点下手。

  统计目标矩阵中每个数出现的次数,对列亦是。若有个操作是L x y,而目标矩阵第x列的值全是y,那显然,这个操作最后一次做是合情合理的,去掉这一列后,又是一个新问题,可以找到新的可以“最后一步”做的操作。依次类推,每次找一个合法的操作,逆序输出即可。

参考代码:

主体代码是队友写的,写的够简洁的~

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct node{
    int t,x,y;
}b[510];
int c[2][110][110],a[110][110],mark[510],ans[510],ans2[510];
char s[10];
bool vis[2][110];
int main(){
    int t,n,m;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&a[i][j]);
        memset(c,0,sizeof(c));
        memset(mark,0,sizeof(mark));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&a[i][j]);
                c[0][j][a[i][j]]++;
                c[1][i][a[i][j]]++;
            }
        int cnt=0,d[2];
        d[0]=n;
        d[1]=n;
        for(int i=0;i<m;i++){
            scanf("%s%d%d",&s,&b[i].x,&b[i].y);
            if(s[0]=='L') b[i].t=0;
                else b[i].t=1;
        }
        memset(vis, 0, sizeof(vis));
        for(int j=0;j<m;j++)
            for(int i=0;i<m;i++)
            if(!mark[i]){
                if(d[b[i].t]==c[b[i].t][b[i].x][b[i].y])
                {
                    if(vis[b[i].t][b[i].x]) continue;
                    vis[b[i].t][b[i].x] = 1;
                    mark[i]=1;
                    ans[m-cnt-1]=i+1;
                    cnt++;
                    d[b[i].t^1]--;
                    for(int k=1;k<=n;k++){
                        if(vis[b[i].t^1][k]) continue;
                        if(b[i].t) c[b[i].t^1][k][a[b[i].x][k]]--;
                        else c[b[i].t^1][k][a[k][b[i].x]]--;
                    }
                }
            }
        int flag=0;
        for(int i=0;i<m;i++)
            if(!mark[i]){
                ans[m-cnt-1]=i+1;
                cnt++;
            }
        for(int i=0;i<m;i++){
            if(flag==1) printf(" ");
            flag=1;
            printf("%d",ans[i]);
        }
        puts("");
    }
}

 

posted @ 2015-08-13 19:40  beisong  阅读(158)  评论(1编辑  收藏  举报