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行输入操作。
  1≤color[i][j]≤n,color[i][j]为数组元素。
  T=5
  1≤n≤100
  1≤m≤500

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

  统计目标矩阵中每个数出现的次数,对列亦是。若有个操作是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("");
    }
}
时间: 2024-10-03 19:30:14

HDU 5386 Cover的相关文章

HDU 5386 Cover(模拟)

Cover Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 966    Accepted Submission(s): 320 Special Judge Problem Description You have an n?n matrix.Every grid has a color.Now there are two types

hdu 5386 Cover(暴力求解+想法题)

题意: 有两种操作: 操作L x y,把当前x,这一列全部置为y 操作H x y,把当前,这一行全部置为y. 现在给你n?n的初始矩阵,以及n?n的目标矩阵 现在给你m种操作(由以上两种操作构成),问怎么排序这m种操作,才能使得,初始矩阵,经由排序后的操作,构成目标矩阵. 输出排序方案. 解析: 逆向思维, 枚举每个操作,然后判断该操作是不是最后一个操作.(就像撕胶布一样,一条一条的剥离) 判断是否是最后一个操作方法就是: 除去已经用过的点,如果一排都等于当前操作的颜色,那就是最后一个操作.然后

HDU 5386 Cover (2015年多校比赛第8场)

1.题目描述:点击打开链接 2.解题思路:本题利用逆向思维+贪心法解决.因为题目中已经告诉我们一定存在解,因此可以考虑贪心法的使用.这道题的妙处在于答案和初始矩阵是无关的,只和目标矩阵有关.因为不管初始矩阵长什么样,只要操作一样,加上解的存在性,得到的目标矩阵一定是相同的.接下来就是如何寻找操作序列. 假设最后一步操作执行后,我们得到了目标矩阵,由于所有操作都是对一整行或者一整列进行的,因此肯定有一行或者一列全部相同.这样,我们就可以从目标矩阵出发,逆着这个过程寻找,如果发现某一行或者一列全部相

HDU 5386 Cover (MUT #8 模拟暴力)

[题目链接]:click here~~ [题意]: 操作L x y,把当前x,这一列全部置为y 操作H x y,把当前,这一行全部置为y. 现在给你n?n的初始矩阵,以及n?n的目标矩阵 现在给你m种操作(由以上两种操作构成),问怎么排序这m种操作,才能使得,初始矩阵,经由排序后的操作,构成目标矩阵. 输出排序方案. 也就是给出初始矩阵和目标矩阵,存在m中操作,可以分别把每行或者每列都涂成同一种颜色,数据保证有解,因为保证有解,(然而初始矩阵并没有什么卵用...) [思路]: 暴力寻找M次操作,

hdoj 5386 Cover

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5386 倒着推的一个挺暴力的题,看着和数学有关系,然而并没有, 不要一看到含有数学元素就考虑这是一个数学题,很有可能用编程思想去推导. 这道题就是倒着暴力去做就行,暴力类的题不容易debug, 注意输入输出一定不要出问题. 1 #include<stdio.h> 2 const int MAXN1 = 105; 3 const int MAXN2 = 505; 4 int T; 5 int m, n

HDU 6311 Cover

Cover Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 440    Accepted Submission(s): 65Special Judge Problem Description The Wall has down and the King in the north has to send his soldiers to s

hdu 6311 Cover (欧拉路径)

#include<bits/stdc++.h> #define N 100005 using namespace std; struct Edge{ int to,next; bool able; }edge[N*4];///要多于总边数的4倍 (*2双向边 并且可能加边) int n,m, Degree[N],///每个点的度 Head[N], ///每个点的最后一条加入的边的序号 cnt, ///边的序号 res; ///一共找到的路径 bool vis[N]; vector<int

HDU 5386 暴力

给出初始矩阵和目标矩阵,存在m中操作,可以分别把每行或者每列都涂成同一种颜色,数据保证有解 因为保证有解,所以初始矩阵完全没有用... 暴力寻找M次操作,若目标矩阵的行或列全和该操作的颜色一样,则最后进行此操作,并把所有涂的点涂为颜色0(可当任意颜色) 然后同样依次推出之前的操作,因为之后的操作会覆盖掉之前操作的点. #include "stdio.h" #include "string.h" struct Mark { int x,y; char op; }mar

hdu 5386 模拟

想明白以后会发现其实就是模拟... 因为每次只能给一整行或者一整列赋值,所以目标矩阵一开始一定有一行或者一列上数字都是相同的,然后找到对应的操作,把那一行或者那一列标记为访问过.然后新的矩阵也一定能找到一行或者一列数字都相同,再找到相应的操作,标记那一行或者那一列,依次类推,然后没有用到的操作随便找个顺序就好了.其实初始矩阵并没有什么用...... 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio>