Description
We say a n*m matrix r is lucky if and only if for every i, j, k, l(0 <= i < k < n, 0 <= j < l < m) r[i][j] + r[k][l] <= r[i][l] + r[k][j], and now you need to decide whether a matrix is luck.
Input
The input contains several test cases. The first line of each case contains two positive integers n and m(0 < n, m <= 2000), And then follow n lines and each line contains m integers. All of the integers are no more than 10^9 and no less than -10^9.
Output
If the matrix is lucky, please print “yes” without double quotation and if not print “no” without double quotation.
Sample Input
1 1 626 3 4 1382 1409 97 606 1548 1708 1973 1114 1626 381 75 799
Sample Output
yes no
让人egg-pain的A题,我本来的思路是用两层循环找到一个点,再用两层循环找到另一个点,以这两个点为对角点建立一个矩形,依次判断条件 r[i][j] + r[k][l] <= r[i][l] + r[k][j] 是否成立,不过我很快发现这样的算法复杂度高达10^12(xiejj也用事实证明了暴搜行不通)。后来从AC的代码中发现了一条诡异的性质:如果一个大矩形的每个子矩形都满足上述条件,那么这个大矩形本身也满足这个条件,我自己也证明出来了,见页面底部。所以只需要用两层循环找到一个点,以这个点做单位矩阵,对每个单位矩阵判断就可以了。唉,不提了,说多了都是泪。。。。。AC过的代码如下:
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cstdio> 5 #include<math.h> 6 #include<cstdlib> 7 using namespace std; 8 int r[2010][2010]; 9 bool flag=1; 10 int main() { 11 int n,m,i,j,k,l; 12 while(~scanf("%d%d",&n,&m)) { 13 if(n==0&&m==0) break; 14 for(i=0; i<n; i++) 15 for(j=0; j<m; j++) 16 scanf("%d",&r[i][j]); 17 for(i=0,k=i+1;k<n&&i<n; i++) 18 for(j=0,l=j+1;flag==1&&l<m&&j<m; j++) 19 //for(k=i+1; k<n; k++) 20 // for(l=j+1; flag==1&&l<m; l++) 21 if(r[i][j] + r[k][l] > r[i][l] + r[k][j]) flag=0; 22 23 if(flag==1) printf("yes\n"); 24 else printf("no\n"); 25 } 26 27 28 return 0; 29 }
性质证明:
x1+x5<=x2+x4 ...........(1)
x2+x6<=x3+x5............(2)
x4+x8<=x5+x7............(3)
x5+x9<=x6+x8............(4)
(1)+(2)+(3)+(4)得:
x1+x9<=x3+x7
即大矩阵满足性质,得证
这是大矩阵为正方形的情况,当其为矩形时,同理可证