[NOIP2018校模擬賽]T2矩陣分組 Matrix
阿新 • • 發佈:2018-10-03
第一個 開始 etc getch break src () 等價 mat
題目鏈接:
矩陣分組
分析:
這道題求的是兩部分極差當中大的那個的最小值。對於這種求最值的問題,我們很自然(其實並沒有)地想到二分答案。
這個題有兩個結論:
(好像當時看出來了第一個?然後發現下面都不會了,果斷棄療滾去寫T3)
第一個結論:
對於劃分的每個區域,為了保證只拐一次彎,它每一行的長度是單調且連續的
這樣任意兩個元素之間拐個直角彎就能到了(x)
參見下圖(從發的solution裏面扒的):
這個結論可以感性得到(……),因為如果它每一行的長度不單調,就會有 凸 ←這種形狀的東西出來,從它的一邊到另外一邊肯定是要拐至少兩個彎的
第二個結論:
矩陣A和矩陣B可以互換(即它們是等價的)
因為每個矩陣不管怎麽講總要占據一個角落(否則不滿足結論1),所以先考慮A占據左上角的情況,然後把它旋轉三次就能涵蓋到所有情況。
二分一個值mid(mid=min(max(gmaxi1-gmini1,gmaxi2,gmini2)),其上界為矩陣中最大值-最小值,下界為0,這樣最後的mid就是答案
對於check函數的思路:
因為矩陣中最大值和最小值不能在一個區域,否則這個max(gmaxi1-gmini1,gmaxi2,gmini2)就會很大,所以我們不妨設tot_max在A區域
從第一行開始找到第一個(找第一個是為了保證單調)與tot_max差值大於mid的值,這時候就跳出循環(這裏每一行的枚舉不能超過上一行的邊界),後面同理,處理出矩陣A,顯然這個矩陣A一定是滿足條件的
然後我們驗證剩下的部分(即矩陣B)當中的極差是否小於等於mid即可
代碼:
沒有代碼,因為我還沒寫出來(……)
#include<bits/stdc++.h> using namespace std; int n,m,x=1,x1=1,x2=n,x3=m,y=1,yy=n,y2=m,y3=1,t; int tot_max=-(1<<20),tot_min=1<<20; int a[4][2005][2005],endi[2005]; //endi中存儲A矩陣每行的邊界 inline int read(){ int cnt=0,f=1;char c; c=getchar(); while(!isdigit(c)){ if(c==‘-‘)f=-1; c=getchar(); } while(isdigit(c)){ cnt=cnt*10+c-‘0‘; c=getchar(); } return cnt*f; } bool check(int kind,int x){ if(kind&1) swap(n,m); // 這裏第二和第四個矩陣是分別順時針逆時針旋轉了90°的,所以行數和列數需要交換 endi[0]=m; int tag; for(register int i=1,j;i<=n;i++){ for(j=1;j<=endi[i-1];j++){ if(tot_max-a[kind][i][j]>x) //找到第一個與tot_max差值小於等於mid的值 break; } endi[i]=j-1; } for(register int i=1;i<=n;i++) for(register int j=endi[i]+1;j<=m;j++) //處理第二個矩陣 if(a[kind][i][j]-tot_min>x){ if(kind&1) swap(n,m); //如果剛剛交換了n和m,為了下次check,這裏需要換回來 return false; } if(kind&1) swap(n,m); return true; } bool tot_check(int x){ if(check(0,x))return true; if(check(1,x))return true; if(check(2,x))return true; if(check(3,x))return true; return false; } int main(){ n=read();m=read(); x=1,x1=1,x2=n,x3=m,y=1,yy=n,y2=m,y3=1; for(register int i=1;i<=n;i++){ //讀入矩陣,讀入的時候就可以順手旋轉成四個矩陣了(順便這個旋轉很巧妙啊) for(register int j=1;j<=m;j++){ t=a[0][x][y++]=a[1][x1++][yy]=a[2][x2][y2--]=a[3][x3--][y3]=read(); if(t>tot_max)tot_max=t; if(t<tot_min)tot_min=t; } x++,y=1,yy--,x1=1,x2--,y2=m,y3++,x3=m; } int l=0,r=tot_max-tot_min; int mid=(l+r)>>1; while(l<r){ if(tot_check(mid)){ r=mid; mid=(l+r)>>1; } else{ l=mid+1; mid=(l+r)>>1; } } printf("%d",mid); return 0; }
[NOIP2018校模擬賽]T2矩陣分組 Matrix