1. 程式人生 > >bzoj5470 / P4578 [FJOI2018]所羅門王的寶藏

bzoj5470 / P4578 [FJOI2018]所羅門王的寶藏

P4578 [FJOI2018]所羅門王的寶藏

設第$i$行上的值改變了$r1[i]$,第$j$列上的值改變了$r2[i]$

顯然密碼$(i,j,c)=r1[i]+r2[j]$

對於同一列上的兩個密碼$(i_{1},j,c_{1}),(i_{2},j,c_{2})$,它們的差值即為$c_{1}-c_{2}=r1[i_{1}]-r1[i_{2}]$

同一行上的同理。

這樣我們就可以確定$r1[i],r2[j]$之間的關係,並以此判斷

那麼對於每組資料,我們可以$O(k^2)$兩兩列舉寶石,用上述方法判斷即可。

同一個地方可能有兩顆寶石

 1 #include<iostream>
 2
#include<cstdio> 3 #include<cstring> 4 #include<cctype> 5 using namespace std; 6 void read(int &x){ 7 char c=getchar();x=0;bool f=1; 8 while(!isdigit(c)) f=(f&&c!='-'),c=getchar(); 9 while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
10 x=f?x:-x; 11 } 12 #define N 1005 13 int n,m,k,x[N],y[N],v[N],d1[N][N],d2[N][N]; 14 bool w1[N][N],w2[N][N],ok; 15 int ask(int i,int j,int c){ 16 if(c) return y[i]<y[j]?v[i]-v[j]:v[j]-v[i]; 17 else return x[i]<x[j]?v[i]-v[j]:v[j]-v[i]; 18 } 19 bool check(int i,int j){ 20 if
(x[i]==x[j]&&y[i]==y[j]&&v[i]!=v[j]) return 0;//同個位置兩顆寶石 21 if(y[i]==y[j]){ 22 if(w1[x[i]][x[j]]&&d1[x[i]][x[j]]!=ask(i,j,0)) return 0; 23 d1[x[i]][x[j]]=d1[x[j]][x[i]]=ask(i,j,0); 24 w1[x[i]][x[j]]=w1[x[j]][x[i]]=1; 25 } 26 if(x[i]==x[j]){ 27 if(w2[y[i]][y[j]]&&d2[y[i]][y[j]]!=ask(i,j,1)) return 0; 28 d2[y[i]][y[j]]=d2[y[j]][y[i]]=ask(i,j,1); 29 w2[y[i]][y[j]]=w2[y[j]][y[i]]=1; 30 }return 1; 31 } 32 int main(){ 33 int T;read(T); 34 while(T--){ 35 memset(d1,0,sizeof(d1)); 36 memset(d2,0,sizeof(d2)); 37 memset(w1,0,sizeof(w1)); 38 memset(w2,0,sizeof(w2)); 39 read(n);read(m);read(k);ok=1; 40 for(int i=1;i<=k;++i) 41 read(x[i]),read(y[i]),read(v[i]); 42 for(int i=1;i<=k&&ok;++i) 43 for(int j=i+1;j<=k&&ok;++j) 44 ok=check(i,j); 45 printf(ok?"Yes\n":"No\n"); 46 }return 0; 47 }
View Code

(神仙做法,學不來學不來)