题目大意:
给定一个n*m的图,方格中的数仅由1和0组成,要求从(1,1)到(n,m)的所有路径都成回文串需要修改的最小数量
思路:
我们先画一个图之后,我们会发现路径要成为字符串,则在斜线上相同,如图:
但是我们在直接遍历斜线的话,会不是很好想,但是也是能写出来的,根据行数和列数的大小分类讨论,总共要遍历个数是(n+m-3)/2,如果(n+m-3)是奇数的话,最中间的那一列我们不用统计,因为(n+m-3)为奇数的话(n+m-1)也是奇数,中间的那一个对应的回文串也就是自己。
代码1:
const int N = 2e5 + 10, M = 5e2 + 10;
int n,m,o;
int a[M][M];
void df()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cin>>a[i][j];
}
int ans=0,t1=0,t2=0,op=(n+m-3)/2;
if(n<=m)
{
for(int i=1;i<=op;i++)
{
int x,y;
x=1;y=i+1;//当前的点
t1=t2=0;
while(y>=1&&x<=n)
{
if(a[x][y]==1)t1++;
else t2++;
x+=1;y-=1;
}
x=n;y=m-i;
while(y<=m&&x>=1)
{
if(a[x][y]==1)t1++;
else t2++;
x-=1;y+=1;
}
ans+=min(t1,t2);
}
}
else
{
for(int i=1;i<=op;i++)
{
int x,y;
x=i+1;y=1;
t1=t2=0;
while(x>=1&&y<=m)
{
if(a[x][y]==1)t1++;
else t2++;
x-=1;
y+=1;
}
x=n-i;y=m;
while(x<=n&&y>=1)
{
if(a[x][y]==1)t1++;
else t2++;
x+=1;
y-=1;
}
ans+=min(t1,t2);
}
}
if(a[1][1]!=a[n][m])ans++;
cout<<ans<<endl;
}
但是还有一种更简单的方法就是我们统计(i+j-1)这一条斜线上的0和1的个数,之后我们再从两边统计即可。
代码2:
const int N = 2e5 + 10, M = 5e2 + 10;
int n,m,o;
int a[M][M],cnt[M][5];
void df()
{
cin>>n>>m;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
cnt[i+j-1][a[i][j]]++;
}
}
int ans=0;
int l=1,r=n+m-1;
while(l<r)
{
ans+=min(cnt[l][0]+cnt[r][0],cnt[l][1]+cnt[r][1]);
l+=1;
r-=1;
}
cout<<ans<<endl;
}