CF1772F 题解
思路
这题有一个很重要的突破口——操作不可逆,所以可操作的次数是不上升的。所以我们可以对每张图片都统计一次可以操作的数量,然后从大到小排序就得到了打乱前的顺序。至于改变的顺序,那就只要看一下相邻两张图片有哪几个格子不一样即可。
代码
// LUOGU_RID: 119511355
# include <bits/stdc++.h>
using namespace std;
typedef pair <int, int> pii; //简写,注意不能放到 using namespace std; 前面,因为 pair 是要用到 std 的
struct node {
string a[35];
int tot, id;
bool operator < (const node& x) const { //重载运算符
return tot > x.tot;
}
} a[105];
int n, m, k;
vector <pii> ans;
bool check (string a[], int i, int j) { //判断是否合法
return a[i][j] != a[i + 1][j] && a[i][j] != a[i - 1][j] && a[i][j] != a[i][j + 1] && a[i][j] != a[i][j - 1];
}
int main () {
cin >> n >> m >> k;
++ k; //k+1 张图片
for (int i = 1; i <= k; ++ i) {
a[i].id = i;
for (reg int j = 1; j <= n; ++ j) {
cin >> a[i].a[j];
a[i].a[j] = ' ' + a[i].a[j];
}
for (reg int j = 2; j < n; ++ j) //注意这部分不能和输入合并到一起!!!否则 a[j+1] 还没输入,你会 WA on #16
for (reg int k = 2; k < m; ++ k)
a[i].tot += check (a[i].a, j, k); //统计有几个可以被修改
}
sort (a + 1, a + k + 1); //排序
for (int i = 1; i < k; ans.push_back ({a[++ i].id, 0}))
for (int j = 2; j < n; ++ j)
for (int k = 2; k < m; ++ k)
if (a[i].a[j][k] != a[i + 1].a[j][k] && check (a[i].a, j, k))
ans.push_back ({j, k});
cout << a[1].id << '\n' << ans.size () << '\n';
for (pii i : ans)
if (i.second)
cout << "1 " << i.first << ' ' << i.second << '\n';
else
cout << "2 " << i.first << '\n';
return 0;
}

浙公网安备 33010602011771号