2 条题解
-
1
第一次场切绿题,发片题解庆祝一下,
嘶,我的思路怎么和题解一样......
题意
简单来说就是给你一个的矩阵,你可以在某一列或某一行刷上或(颜色会被覆盖,往后用笔触代表这个意思),给出一种可以从白墙刷成目标矩阵的方案,没有方案输出
大体思路
首先想要正着推肯定是做不出来的,所以考虑倒推,由题意得,我们可以在每找到笔触时就记录并将这一行或这一列删去(赋值为),因为这一笔会覆盖原来的笔画,所以去掉后并不会太影响答案
实现
首先注意删去一个笔触后,画布上也会少一行或者一列,再开一个代表还剩下的行数,代表还剩下的列数,每找到一个笔触,对应和,接下来的寻找就找一行中一个颜色是否与现在的相等,一列中一个颜色是否与现在的相等
然后考虑时间复杂度,如果我们纯按照以上思路就大概是,据的评测记录会四个点.....
所以我们要优化掉一点,就可以开两个数组代表第行第种颜色的数量(,因为画相当于没画)
同理,代表第列第种颜色的数量,按照上面思路模拟即可,时间大概为
细节
我们这个思路再判断是有一个细节:
我们是默认不算,因为画等于白画,所以有存在的点始终没有删去,但是初始颜色,不能导致结果为,所以当找不到笔触时,还要把矩阵遍历一遍,当有点的颜色不为时才输出
还有,我们用的是倒推法,所以输出时记得从头到尾输出
#include<bits/stdc++.h> using namespace std; struct node{int x,y,z;}k[4010]; int n,id=0,a[2010][2010],ch[2010][5],cl[2010][5]; bool vl[2010],vh[2010]; int main() { scanf("%d",&n); int h=n,l=n; for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) { vh[i]=vl[j]=1; scanf("%d",&a[i][j]); ch[i][a[i][j]]++;cl[j][a[i][j]]++; } while(h&&l) { bool f=0; for(int i=1;i<=n;i++)if(vh[i]) { for(int j=1;j<=2;j++)if(ch[i][j]==l) { vh[i]=0; k[++id]={1,i,j}; f=1; for(int p=1;p<=n;p++) { cl[p][j]--; a[i][p]=-1; } h--; } } if(!h)break; for(int i=1;i<=n;i++)if(vl[i]) { for(int j=1;j<=2;j++)if(cl[i][j]==h) { vl[i]=0; k[++id]={2,i,j}; f=1; for(int p=1;p<=n;p++) { ch[p][j]--; a[p][i]=-1; } l--; } } if(!f) { for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) { if(a[i][j]>0){puts("-1");return 0;} } break; } } printf("%d\n",id); for(int i=id;i;i--)printf("%d %d %d\n",k[i].x,k[i].y,k[i].z); return 0; }tip,的结构体只开了,竟然是不是
-
0
解题思路
首先看完题目,然后发现很难,接着开始写代码,最后一片青青草原。
考虑倒着思考。最后一次操作一定会让某一行/列全部为 或者全部为 ,那么我们每一次只需要删除全为 或者全为 的行/列,一直到不能操作,然后判断整个地图是否全是 即可。
如果我们直接暴力删除其实是不好模拟的,所以我们用两个变量来表示地图剩下的行数、列数,然后将删除的行/列全部赋值为 ,代表当前点不可用,最后统计的时候判断是否全是 即可。
CODE:
#include <bits/stdc++.h> using namespace std; #define int long long int a[2010][2010], h[2010][10], l[2010][10]; struct node { int a, b, c; }; bool vish[2010], visl[2010]; vector<node> v; signed main() { ios::sync_with_stdio(false); ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0); int n; cin >> n; int hh = n, ll = n; for (int i = 1; i <= n; i++) { vish[i] = visl[i] = 1; for (int j = 1; j <= n; j++) { cin >> a[i][j]; h[i][a[i][j]]++; l[j][a[i][j]]++; } } while (hh && ll) { bool flag = false; for (int i = 1; i <= n; i++) { if (vish[i]) { for (int j = 1; j <= 2; j++) { if (h[i][j] == ll) { vish[i] = 0; v.push_back({1, i, j}); flag = true; for (int k = 1; k <= n; k++) { l[k][j]--; a[i][k] = -1; } hh--; } } } } if (!hh) { break; } for (int i = 1; i <= n; i++) { if (visl[i]) { for (int j = 1; j <= 2; j++) { if (l[i][j] == hh) { visl[i] = 0; flag = true; v.push_back({2, i, j}); for (int k = 1; k <= n; k++) { a[k][i] = -1; h[k][j]--; } ll--; } } } } if (!flag) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (a[i][j] > 0) { cout << "-1\n"; return 0; } } } break; } } cout << v.size() << "\n"; for (int i = v.size() - 1; i >= 0; i--) { cout << v[i].a << ' ' << v[i].b << ' ' << v[i].c << "\n"; } return 0; }
- 1
信息
- ID
- 12552
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 70
- 已通过
- 15
- 上传者