P11476 [COCI 2024/2025 #3] 涂矩阵 / Bojanje
题目背景
译自 COCI 2024/2025 #3 T3。 1s,0.5G \texttt{1s,0.5G} 1s,0.5G。满分为 90 90 90。
题目描述
有一个初始为全白的 n × n n\times n n×n 矩阵。
每次操作可以选择一列 / 一行,将这一列 / 一行覆盖成红色 / 蓝色。
给定矩阵的目标状态,试构造一组操作序列使得矩阵达到目标状态,或者报告无解。
不需要最小化操作序列的长度,合法即可得分。
输入格式
第一行,一个正整数 n n n。
接下来 n n n 行,每行 n n n 个正整数,第 i i i 行第 j j j 个整数 a i , j a_{i,j} ai,j 描述目标状态中第 i i i 行第 j j j 列格子的颜色: 0 0 0 表示白色, 1 1 1 表示红色, 2 2 2 表示蓝色。
输出格式
如果无解,输出 − 1 -1 −1。
否则,第一行输出一个整数 k k k,表示操作序列长度。你需要保证 0 ≤ k ≤ 4 000 0\le k\le 4\, 000 0≤k≤4000。
接下来 k k k 行,每行三个正整数 a , b , c a,b,c a,b,c,依次描述操作:
- a ∈ { 1 , 2 } a\in \{1,2\} a∈{1,2}: a = 1 a=1 a=1 代表选择的是行, a = 2 a=2 a=2 代表选择的是列。
- 1 ≤ b ≤ n 1\le b\le n 1≤b≤n:代表选择的是第 b b b 行(列)。
- c ∈ { 1 , 2 } c\in \{1,2\} c∈{1,2}:代表涂的是什么颜色。 1 1 1 表示红色, 2 2 2 表示蓝色。
输入输出样例 #1
输入 #1
3
0 0 1
1 1 1
0 0 1
输出 #1
2
2 3 1
1 2 1
输入输出样例 #2
输入 #2
3
1 1 2
2 1 1
2 1 1
输出 #2
-1
输入输出样例 #3
输入 #3
4
0 1 2 1
2 2 2 1
0 1 2 1
1 1 2 1
输出 #3
5
2 2 1
1 2 2
2 4 1
1 4 1
2 3 2
说明/提示
对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 2 × 10 3 1\le n\le 2\times 10^3 1≤n≤2×103。
| 子任务编号 | k ≤ k\le k≤ | 特殊性质 | 得分 |
|---|---|---|---|
| $ 1 $ | 2 × 10 3 2\times 10^3 2×103 | A | $ 15 $ |
| $ 2 $ | 10 2 10^2 102 | $ 35 $ | |
| $ 3 $ | 2 × 10 3 2\times 10^3 2×103 | $ 40 $ |
- 特殊性质 A: a i , j ∈ { 0 , 1 } a_{i,j}\in\{0,1\} ai,j∈{0,1}。
C++实现
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct ans{int a,b,c;}ans[4005];
int n,a[2005][2005],w[3][2005],h[3][2005],cnt;
bool check(){
bool flag=0;
for(int i=1;i<=n;i++){
if((w[1][i]>0&&w[2][i]==0||w[2][i]>0&&w[1][i]==0)&&w[0][i]==0||(h[1][i]>0
&&h[2][i]==0||h[2][i]>0&&h[1][i]==0)&&h[0][i]==0)return 1;//有一列或有一行全是1或2,返回1继续删
if(w[1][i]>0||w[2][i]>0||h[1][i]>0||h[2][i]>0)flag=1;
}
if(flag){
cout<<-1;
exit(0);
}
return 0;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>a[i][j],w[a[i][j]][i]++,h[a[i][j]][j]++;//记录每一列和每一行0,1,2的个数
while(check()){
for(int i=1;i<=n;i++){//删行
if(w[0][i]>0||w[1][i]>0&&w[2][i]>0)continue;//有0或者既有1又有2
if(w[1][i]>0){//全是1
ans[++cnt]={1,i,1},w[1][i]=0;
for(int i=1;i<=n;i++)h[1][i]--;
}
if(w[2][i]>0){//全是2
ans[++cnt]={1,i,2},w[2][i]=0;
for(int i=1;i<=n;i++)h[2][i]--;
}
}
for(int i=1;i<=n;i++){//删列
if(h[0][i]>0||h[1][i]>0&&h[2][i]>0)continue;//有0或者既有1又有2
if(h[1][i]>0){//全是1
ans[++cnt]={2,i,1},h[1][i]=0;
for(int i=1;i<=n;i++)w[1][i]--;
}
if(h[2][i]>0){//全是2
ans[++cnt]={2,i,2},h[2][i]=0;
for(int i=1;i<=n;i++)w[2][i]--;
}
}
}
cout<<cnt;
for(int i=cnt;i>0;i--)cout<<"\n"<<ans[i].a<<" "<<ans[i].b<<" "<<ans[i].c;
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
用C++实现信奥题 P11476 COCI 20242025 #3 涂矩阵 Bojanje&spm=1001.2101.3001.5002&articleId=165835217&d=1&t=3&u=9651b56686424a27a20513bacff7cc8e)
562

被折叠的 条评论
为什么被折叠?



