Educational Codeforces Round 89C. Palindromic Paths
题目链接
https://codeforc.es/contest/1366/problem/C
题意
题意是有个01矩阵,完了要改最小数量的格子,使得左上角到右下角的所有路径是回文路径。
三禁忌
活了这么大,我总结出了世界上三个绝对不能碰的禁忌:
-
烤了1小时鸡腿的烤箱
-
地宫东南角的蜡烛灭掉之后,棺材里的冥器。
-
CF的EDU局
-
头一样东西小时候总是舔,完了舌头暂时报废次数多了,现在渐渐不嘴欠了。
-
第二样东西是书上说的,我自己也没试过,有兴趣可以趁着月黑风高去试试,但是能不能生存下来就不好说了。
-
但是后一样,真的忍不住,屡教不改,每次都掉分,但总有上分的侥幸心理。这可能跟赌徒发誓不在碰老千,完了剁手都忍不住一样。。。
这次我又没忍住,果然死的很难看。
题解
一道c题整这么难。仔细想想就会发现满足条件的矩阵满足一些性质:矩阵中心对称(保证回文),各个主对角线上,每条对角线元素必须相同(保证同距离相同),但是回文长度为奇数的话中间一个对角线可以不变。那么就只要看看每条对角线那0多还是1多就完了。少数服从多数。
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int NN=40;
int aa[NN][NN],a[NN][NN];
int main(){
int t;scanf("%d",&t);
while(t--){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&aa[i][j]);
if(n>m){
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)a[i][j]=aa[j][i];
}
swap(n,m);
}
else{
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=aa[i][j];
}
int len=n+m-1;
int ans=0;
if(len%2){
for(int i=1;i<=len/2;i++){
int up=min(i,n);
int rec0=0,rec1=0;
for(int j=1;j<=up;j++){
if(a[j][i-j+1]==1)rec1++;
else rec0++;
if(a[n-j+1][m-i+j]==1)rec1++;
else rec0++;
}
ans+=min(rec0,rec1);
}
}
else{
for(int i=1;i<=len/2;i++){
int up=min(i,n);
int rec0=0,rec1=0;
for(int j=1;j<=up;j++){
if(a[j][i-j+1]==1)rec1++;
else rec0++;
if(a[n-j+1][m-i+j]==1)rec1++;
else rec0++;
}
ans+=min(rec0,rec1);
}
}
printf("%d\n",ans);
}
return 0;
}
我这个代码写丑了,其实两种情况代码是一样的。