You are given a grid with nn rows and mm columns. We denote the square on the i-th (1≤i≤n) row and j-th (1≤j≤m) column by (i,j) and the number there by aij. All numbers are equal to 1 or to −1.
You start from the square (1,1) and can move one square down or one square to the right at a time. In the end, you want to end up at the square (n,m).
Is it possible to move in such a way so that the sum of the values written in all the visited cells (including a11 and anm) is 0?
Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤10^4). Description of the test cases follows.
The first line of each test case contains two integers n and m (1≤n,m≤1000) — the size of the grid.
Each of the following n lines contains mm integers. The j-th integer on the i-th line is aij (aij=1 or −1) — the element in the cell (i,j).
It is guaranteed that the sum of n⋅m over all test cases does not exceed 10^6.
Output
For each test case, print "YES" if there exists a path from the top left to the bottom right that adds up to 0, and "NO" otherwise. You can output each letter in any case.
Example
input
5 1 1 1 1 2 1 -1 1 4 1 -1 1 -1 3 4 1 -1 -1 -1 -1 1 1 -1 1 1 1 -1 3 4 1 -1 1 1 -1 1 -1 1 1 -1 1 1
output
NO YES YES YES NO
Note
One possible path for the fourth test case is given in the picture in the statement.
题意: 有一个由-1和1组成的矩阵,询问是否存在一条从(1, 1)到(n, m)的路径,移动时只能向右或向下走,其路径和为0。
分析: 利用dp可以求出从(1, 1)到(n, m)的最大值max和最小值min,如果min <= 0 <= max,则一定存在一条路径能从(1, 1)走到(n, m)且路径和为0。
下面给出证明:存在如下一条路径,沿着上边界和右边界到达(n, m),
此时可以将右上角的点变换至其左下方以得到一条新路径,
此时路径和从原来的路径和基础上增加了2 ,之后以同样方式可以得到更多的新路径,最终以此方式可以遍历得到全部的路径,在过程中显然会遍历得到最小值路径min和最大值路径max,也就是说一定存在一个路径和从min值增加到max值的过程,而这个过程中路径值每次都会增减2,所以一定会经过值为0的状态,也就得到了路径值为0的一条路径。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#define inf 0x3f3f3f3f
using namespace std;
int a[1005][1005], mi[1005][1005], ma[1005][1005];
signed main()
{
int T;
cin >> 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", &a[i][j]);
ma[1][1] = mi[1][1] = a[1][1];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++){
if(i == 1 && j == 1) continue;
mi[i][j] = min(i-1>=1?mi[i-1][j]:inf, j-1>=1?mi[i][j-1]:inf)+a[i][j];
ma[i][j] = max(i-1>=1?ma[i-1][j]:-inf, j-1>=1?ma[i][j-1]:-inf)+a[i][j];
}
if((n+m-1)&1) puts("NO");
else if(mi[n][m] <= 0 && ma[n][m] >= 0) puts("YES");
else puts("NO");
}
return 0;
}