1. 程式人生 > 實用技巧 >2020小米選拔賽D 二維差分套字首和 Matrix Subtraction

2020小米選拔賽D 二維差分套字首和 Matrix Subtraction

原題:https://ac.nowcoder.com/acm/contest/7501/J

大致題意:給你一個n x m的矩陣,我們可以對其中任意一個a x b的矩陣進行操作(所有元素減一)。可以進行無限次操作,每次可以選任意一個a x b的矩陣。 求問是否可以讓n x m的矩陣內的所有元素為零

思路:

對於nxm的矩陣,從左上角第一個元素in[1][1]開始,如果要讓nxm的矩陣所有元素為零,那麼在in[1][1]上必須進行in[1][1]次操作,而對in[1][1]可進行操作的axb的矩陣是唯一的。

處理完in[1][1]後,我們需要記錄從1 1 到a b這個矩陣內已經減掉了in[1][1]這個事實。所以我們可以用一個二維資料deduct[i][j]來記錄當前ij點上的在之前的操作中刪去的個數。

deduct在遍歷的過程中轉化為字首和。而當在ab範圍內減去一個數字的時候進行差分。

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 typedef long long ll;
 5 const int mx=1e3+10;
 6 ll deduct[mx][mx], in[mx][mx];
 7 int main(){
 8     ll T, n, m, a, b;
 9     scanf("%lld", &T);
10     for(ll lp=1;lp<=T;lp++){
11 scanf("%lld %lld %lld %lld", &n, &m, &a, &b); 12 for(ll i=1;i<=n;i++) { 13 for (ll j = 1; j <= m; j++) 14 scanf("%lld", &in[i][j]); 15 } 16 memset(deduct, 0, sizeof(deduct)); 17 bool ok=true; 18 for
(ll i=1;i<=n&&ok;i++){ 19 for(ll j=1;j<=m&&ok;j++){ 20 deduct[i][j]+=deduct[i-1][j]+deduct[i][j-1]-deduct[i-1][j-1]; 21 //求字首和 22 if(deduct[i][j]>in[i][j]){//如果已經減去的數量比當前的數值大了 不可能為0 23 ok=false; 24 break; 25 } 26 else if(deduct[i][j]<in[i][j]){//如果比當前的數量小 意味著還要繼續減 27 ll t=in[i][j]-deduct[i][j]; 28 if(i+a-1>n||j+b-1>m){ 29 ok=false; 30 break; 31 } 32 //差分 33 //當前的減了 axb範圍內的資料都要減 34 deduct[i][j]+=t, deduct[i+a][j+b]+=t; 35 deduct[i+a][j]-=t, deduct[i][j+b]-=t; 36 } 37 } 38 } 39 printf("%s\n", ok?"^_^":"QAQ"); 40 } 41 return 0; 42 }