HDU 5386 Cover(暴力+逆推)——多校练习8

通过逆向思维,解决矩阵操作顺序问题,确保从初始状态转换为目标状态。

Cover

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Special Judge

Problem Description
You have an  nn  matrix.Every grid has a color.Now there are two types of operating:
L x y: for(int i=1;i<=n;i++)color[i][x]=y;
H x y:for(int i=1;i<=n;i++)color[x][i]=y;
Now give you the initial matrix and the goal matrix.There are  m  operatings.Put in order to arrange operatings,so that the initial matrix will be the goal matrix after doing these operatings

It's guaranteed that there exists solution.
 

Input
There are multiple test cases,first line has an integer  T
For each case:
First line has two integer  n , m
Then  n  lines,every line has  n  integers,describe the initial matrix
Then  n  lines,every line has  n  integers,describe the goal matrix
Then  m  lines,every line describe an operating

1color[i][j]n
T=5
1n100
1m500
 

Output
For each case,print a line include  m  integers.The i-th integer x show that the rank of x-th operating is  i
 

Sample Input
  
1 3 5 2 2 1 2 3 3 2 1 3 3 3 3 3 3 3 3 3 3 H 2 3 L 2 2 H 3 3 H 1 3 L 2 3
 

Sample Output
  
5 2 4 3 1
 

Source
 
/*********************************************************************/

题意:有两类操作:①L x y 把矩阵的第x列涂成同一种颜色y;②H x y 把矩阵的第x行涂成同一种颜色y

给你n*n的初始矩阵、目标矩阵和m种操作,问如何安排操作顺序,使得初始矩阵能够转换成目标矩阵。

放上出题人的题解报告


正如上述所说,初始矩阵是没有用处的

解题思路:逆向思维 
枚举每个操作,然后判断该操作是不是最后一个操作。(就像撕胶布一样,一条一条的剥离)
判断是否是最后一个操作的方法是:
除去已经用过的点(
即标记成0的点,可以充当任何颜色),如果操作的那一排都等于当前操作的颜色,那就是最后一个操作。然后再把操作过的点给标记,重复m次。
最后逆向输出记录下的操作的编号即可。

若有疑问的地方,欢迎指出,谢谢!

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 105;
const int inf = 1000000000;
const int mod = 258280327;
int c[N][N],a[5*N],s[5*N][2],x[5*N],y[5*N];
int main()
{
    int t,n,m,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                scanf("%d",&c[i][j]);//初始矩阵
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                scanf("%d",&c[i][j]);//目标矩阵
        for(i=1;i<=m;i++)
            scanf("%s%d%d",s[i],&x[i],&y[i]);//操作
        k=0;
        while(m>k)
            for(i=1;i<=m;i++)
                if(x[i])
                    if(s[i][0]=='L')//列操作
                    {
                        for(j=1;j<=n;j++)
                            if(c[j][x[i]]&&c[j][x[i]]!=y[i])//若一列存在多种颜色,跳出
                                break;
                        if(j>n)//一列全为一种颜色,将其标记成0,可充当任何颜色
                        {
                            a[k++]=i;
                            for(j=1;j<=n;j++)
                                c[j][x[i]]=0;
                            x[i]=0;
                        }
                    }
                    else//行操作
                    {
                        for(j=1;j<=n;j++)
                            if(c[x[i]][j]&&c[x[i]][j]!=y[i])//若一行存在多种颜色,跳出
                                break;
                        if(j>n)//一行全为一种颜色,将其标记成0,可充当任何颜色
                        {
                            a[k++]=i;
                            for(j=1;j<=n;j++)
                                c[x[i]][j]=0;
                            x[i]=0;
                        }
                    }
        for(i=k-1;i>0;i--)
            printf("%d ",a[i]);
        printf("%d\n",a[i]);
    }
    return 0;
}
菜鸟成长记

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值