大家都很强, 可与之共勉 。
一道好题,嗯。
题意
给出一个R*C的棋盘.共有R行C列,R*C个格子.现要在每个格子都填一个非负整数.使得任意一个2*2的正方形区域都满足这样的性质:左上角的数字+右下角的数字=左下角的数字+右上角的数字.有些格子已经确定,你不能更改其中的数字.其他格子的数字由你决定.A想要知道一个可行的填充棋盘的方案.但是这个方案可能很大.所以你只需对给定的棋盘判定是否存在至少一种可行的填充棋盘的方案.
Bfs或者Dfs判矛盾,主要注意对于任意一列,任意两行之间元素的差相等。任意一行同样。,且解都为非负整数。
#include <bits/stdc++.h>
# define Size 1000000
inline int readInt ( ) {
register int x, c ;
static char buf [Size], *ss, *tt ;
# define pick( ) ( (ss == tt) ? ( tt = buf + fread ( ss = buf, 1, Size, stdin ), ( ss == tt ) ? -1 : *ss ++ ) : *ss ++ )
while ( ! isdigit ( c = pick ( ) ) ) ;
for ( x = -48 + c ; isdigit ( c = pick ( ) ) ; x = x * 10 + c - 48 ) ;
return x ;
# undef pick
}
inline void smin ( long long& d, long long x ) { ( d > x ) ? d = x : 0 ; }
const long long inf = ( ~0ull >> 1 ) ;
const int N = 200010 ;
int q [N] ;
bool inq [N] ;
long long a [N] ;
struct edge {
int to, w ; edge* nxt ;
} g [N], *head [N], *NewEdge ;
int main ( ) {
int h, w, n ;
h = readInt ( ), w = readInt ( ), n = readInt ( ) ;
NewEdge = g ;
for ( int i = 0 ; i < n ; ++ i ) {
int x = readInt ( ), y = readInt ( ), z = readInt ( ) ;
-- x, -- y ;
*( ++ NewEdge ) = ( edge ) { h + y, z, head [x] } ; head [x] = NewEdge ;
*( ++ NewEdge ) = ( edge ) { x, z, head [h + y] } ; head [h + y] = NewEdge ;
}
for ( int i = 0, l = h + w ; i < l ; ++ i ) {
if ( ! inq [i] ) {
register edge* it ;
register int fr ( 0 ), tl ( 0 ) ;
a [i] = 0 ;
q [++ tl] = i ;
inq [i] = true ;
while ( fr ^ tl ) {
int u = q [++ fr] ;
for ( it = head [u] ; it ; it = it -> nxt ) {
int r = it -> to, v = it -> w ;
if ( inq [r] ) {
if ( a [u] + a [r] != v ) {
return puts ( "No" ), 0 ;
}
continue ;
}
q [++ tl] = r ;
inq [r] = true ;
a [r] = v - a [u] ;
}
}
long long m1 = inf, m2 = inf ;
while ( tl ) {
( q [tl] < h ) ? smin ( m1, a [q [tl --]] ) : smin ( m2, a [q [tl --]] ) ;
}
if ( m1 + m2 < 0 ) {
return puts ( "No" ), 0 ;
}
}
}
return puts ( "Yes" ), 0 ;
}