A - Lucky
Time Limit:1000MS Memory
Limit:131072KB 64bit IO
Format:%lld & %llu
Submit Status Practice NENU
1081
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)+(3)得:
x1+x9<=x3+x7
即大矩阵满足性质,得证
这是大矩阵为正方形的情况,当其为矩形时,同理可证