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
5 2 4 3 1
题意:有两类操作:①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; }菜鸟成长记