「ZJOI2007」「LuoguP1169」棋盤製作(並查集
題目描述
國際象棋是世界上最古老的博弈遊戲之一,和中國的圍棋、象棋以及日本的將棋同享盛名。據說國際象棋起源於易經的思想,棋盤是一個8×88 \times 88×8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。
而我們的主人公小Q
,正是國際象棋的狂熱愛好者。作為一個頂尖高手,他已不滿足於普通的棋盤與規則,於是他跟他的好朋友小W
決定將棋盤擴大以適應他們的新規則。
小Q
找到了一張由N×MN \times MN×M個正方形的格子組成的矩形紙片,每個格子被塗有黑白兩種顏色之一。小Q
想在這種紙中裁減一部分作為新棋盤,當然,他希望這個棋盤儘可能的大。
不過小Q
還沒有決定是找一個正方形的棋盤還是一個矩形的棋盤(當然,不管哪種,棋盤必須都黑白相間,即相鄰的格子不同色),所以他希望可以找到最大的正方形棋盤面積和最大的矩形棋盤面積,從而決定哪個更好一些。
於是小Q
找到了即將參加全國資訊學競賽的你,你能幫助他麼?
輸入輸出格式
輸入格式:包含兩個整數NNN和MMM,分別表示矩形紙片的長和寬。接下來的NNN行包含一個N ×MN \ \times MN ×M的010101矩陣,表示這張矩形紙片的顏色(000表示白色,111表示黑色)。
輸出格式:包含兩行,每行包含一個整數。第一行為可以找到的最大正方形棋盤的面積,第二行為可以找到的最大矩形棋盤的面積(注意正方形和矩形是可以相交或者包含的)。
輸入輸出樣例
輸入樣例#1: 複製3 3 1 0 1 0 1 0 1 0 0
4 6
說明
對於20%20\%20%的資料,N,M≤80N, M ≤ 80N,M≤80
對於40%40\%40%的資料,N,M≤400N, M ≤ 400N,M≤400
對於100%100\%100%的資料,N,M≤2000N, M ≤ 2000N,M≤2000
題解
某天中午去吃超好吃的魚粉,路上,一位選手問我們,
你知道懸線法是什麼嗎?!
我不知道,於是我問他是幹嘛的,於是他洋洋灑灑的擺出了這道題。
我kiao,這不就是我校傳了好幾屆的最大矩陣題嗎?!
然後我把那道題改造了一下,成功AC。
————————————
跟原題不同的是,我們傳承字首和時的條件改為此位和上一位不同。
並且和左右接通時,判斷是否不同。如果相同就不連。
1 /* 2 qwerta 3 P1169 [ZJOI2007]棋盤製作 4 Accepted 5 100 6 程式碼 C++,1.5KB 7 提交時間 2018-10-14 21:34:02 8 耗時/記憶體 9 29ms, 688KB 10 */ 11 // luogu-judger-enable-o2 12 #include<iostream> 13 #include<cstdio> 14 #include<queue> 15 #include<cmath> 16 using namespace std; 17 #define R register 18 int s[2003]; 19 int a[2003]; 20 struct emm{ 21 int nod,v; 22 }; 23 struct cmp{ 24 bool operator()(emm qaq,emm qwq){ 25 return qaq.v<qwq.v; 26 } 27 }; 28 priority_queue<emm,vector<emm>,cmp>q; 29 int siz[2003],fa[2003]; 30 bool sf[2003]; 31 int fifa(int x) 32 { 33 if(fa[x]==x)return x; 34 return fa[x]=fifa(fa[x]); 35 } 36 inline void con(int x,int y) 37 { 38 int u=fifa(x),v=fifa(y); 39 siz[u]+=siz[v]; 40 fa[v]=u; 41 return; 42 } 43 inline int read() 44 { 45 char ch=getchar(); 46 int x=0; 47 while(!isdigit(ch))ch=getchar(); 48 if(isdigit(ch)){if(ch=='1')x=1;ch=getchar();} 49 return x; 50 } 51 int main() 52 { 53 //freopen("a.in","r",stdin); 54 int n,m; 55 scanf("%d%d",&n,&m); 56 int ansz=0,ansc=0; 57 for(R int i=1;i<=n;++i) 58 { 59 for(R int i=1;i<=m;++i) 60 { 61 int x=read(); 62 if(a[i]+x==1)s[i]++; 63 else s[i]=1; 64 a[i]=x; 65 q.push((emm){i,s[i]}); 66 } 67 for(R int i=1;i<=m;++i) 68 fa[i]=i,siz[i]=1,sf[i]=0; 69 a[0]=a[m+1]=2; 70 while(!q.empty()) 71 { 72 int i=q.top().nod,x=q.top().v;q.pop(); 73 sf[i]=1; 74 if(a[i-1]+a[i]==1&&sf[i-1]) 75 con(i-1,i); 76 if(a[i]+a[i+1]==1&&sf[i+1]) 77 con(i,i+1); 78 int fi=fifa(i),mi=min(siz[fi],x); 79 ansz=max(ansz,mi*mi); 80 ansc=max(ansc,siz[fi]*x); 81 } 82 } 83 printf("%d\n%d",ansz,ansc); 84 return 0; 85 }