你会得到一个有n行(从1到n编号)和m列(从1到m编号)的矩阵。一个数字ai,j被写在属于第i行和第j列的单元格中,每个数字不是0就是1。
一个芯片最初在单元格(1,1)中,它将被移动到单元格(n,m)中。在每次移动过程中,它要么移动到当前行的下一个单元,要么移动到当前列(如果当前单元是(x,y),那么在移动之后,它可以是(x+1,y)或(x,y+1))。芯片不能离开矩阵。
考虑芯片从(1,1)到(n,m)的每条路径。如果第一个单元格中的数字等于最后一个单元格中的数字,第二个单元格中的数字等于倒数第二个单元格中的数字,以此类推,那么这条路径就被称为顺行。
你的目标是改变最小数量的单元格中的数值,使每条路径都是顺行的。
输入
第一行包含一个整数t(1≤t≤200)--测试案例的数量。
每个测试案例的第一行包含两个整数n和m(2≤n,m≤30)--矩阵的尺寸。
然后是n行,第i行包含m个整数ai,1, ai,2, ..., ai,m(0≤ai,j≤1)。
输出
对于每个测试案例,打印一个整数--你必须改变的最小单元格数,以使矩阵中的每个路径都是顺行的。
题意:
给你一个n*m的矩阵,里面每一位只有0和1,起点从1,1到n,m只能向下,或向左走,
考虑芯片从(1,1)到(n,m)的每条路径。如果第一个单元格中的数字等于最后一个单元格中的数字,第二个单元格中的数字等于倒数第二个单元格中的数字,以此类推,那么这条路径就被称为顺行。
你的目标是改变最小数量的单元格中的数值,使每条路径都是顺行的。
题解:
每一条颜色相同的斜线所有的元素都应该是相同的,所以我们只需要考虑,每两条颜色相同的斜线0的数量相加,1的数量相加,看哪个最小加上即可
按每条斜线模拟遍历,实在有点麻烦,我们通过观察发现,每条斜线上的点i+j-1的值都是相同的,
所以只需要开一个二维数组就可以很容易的把每条斜线的0的个数,1的个数存起来
最终双指针遍历即可
#include <cstring>
#include <iostream>
#include <map>
#include <algorithm>
#include <vector>
#include<queue>
using namespace std;
int t;
int a[40][40];
int cnt[100][100];
int main()
{
cin >> t;
while(t--)
{
int n,m;
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++;
r--;
}
cout<<ans<<"\n";
}
}