模擬賽38 B. T形覆蓋 大模擬

liuchanglc發表於2020-11-25

題目描述

如果玩過俄羅斯方塊,應該見過如下圖形:

我們稱它為一個 \(T\) 形四格拼板 。其中心被標記為\(×\)

小苗畫了一個 \(m\)\(n\) 列的長方形網格。行從 \(0\)\(m-1\) 編號,列從 \(0\)\(n-1\) 編號。

她將網格中的一些格子標記為 特殊格子 。

然後,她想要她的朋友幫助她將 \(T\) 形四格拼板按找如下規則擺放:

\(1\)、 特殊格子的數量與 \(T\) 形四格拼板的數量相同,每個 \(T\) 形四格拼板的中心在網格上的位置必須是特殊格子。

\(2\)\(T\) 形四格拼板之間不能有重疊部分。

\(3\)、 所有拼板的部分均在網格內。

注意,\(T\) 形四格拼板有四種擺放方式:

如果方案不存在,輸出 \(No\),否則請找出一種方案使得被拼板覆蓋的數總和最大,求出這個最大值。

輸入格式

從檔案 \(t-covering.in\) 中讀入資料。

第一行兩個整數 \(m,n\) 分別表示行數和列數。

接下來 \(m\) 行,每行 \(n\) 個整數,第 \(i\) 行第 \(j\) 個數(從 \(0\) 開始編號)表示方格中第 \(i\) 行第 \(j\) 列的數 \(a_{i,j}\)

接下來一行,一個整數 \(k\) ,表示特殊格子的數量。

接下來 \(k\) 行,每行兩個整數 \(r_i,c_i\),表示第 \(i\) 個被標記的特殊格子的位置。

輸出格式

如果有方案,輸出可能的被覆蓋的格子內數總和的最大值,否則輸出 \(No\)

注意,本題 \(10\) 組測試資料均綁點, 只輸出 \(1\)\(No\) 不會得分.

樣例

樣例輸入

5 6
7 3 8 1 0 9
4 6 2 5 8 3
1 9 7 3 9 5
2 6 8 4 5 7
3 8 2 7 3 6
3
1 1
2 2
3 4

樣例輸出

67

【樣例 \(1\) 解釋】

其中一種最優的方案如下:

\((1,1)\) 位置的擺放方式為 \(⊣\)

\((2,2)\) 位置的擺放方式為\(⊢\)

\((3,4)\) 位置的擺放方式為 \(⊥\)
樣例 \(2\) 輸入

5 6
7 3 8 1 0 9
4 6 2 5 8 3
1 9 7 3 9 5
2 6 8 4 5 7
3 8 2 7 3 6
3
1 1
2 2
3 3

【樣例 \(2\) 輸出】

No

資料範圍與提示

分析

把這道題打成了大模擬
思路是這樣的:
\(1\)、把所有必須選的格子選上,這樣的 \(T\) 有三種

第一種是在邊界上,第二種是兩個格子直接相鄰,第三種是兩個格子對角線相鄰
在沒有限制的情況下,每一個 \(T\) 可以在周圍的四個格子中任意選三個
而給了限制之後就只能選固定的三個了
要注意在選擇過程中我們選擇了一個格子後會使其它 \(T\) 能選擇的格子減少
也就是說只能選擇固定格子的 \(T\) 增加了,這個要存一下
\(2\)、對於兩個 \(T\) 相隔一個格子的情況用並查集維護

把所有相隔一個格子的 \(T\)合併,如果形成的聯通塊沒有環,可以貪心去掉一個最小的
如果有一個環,必須全部選上
如果有兩個環即以上,則不合法
\(3\)、剩下的貪心去掉最小的即可

程式碼

#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<iostream>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e6+5;
int n,m,k,cnt;
std::vector<int> a[maxn],id[maxn];
bool jud=0,vis[maxn],haha[maxn],inq[maxn],huan[maxn],s[maxn];
int tot[maxn],zxz[maxn],ans=0,js[maxn],sta[maxn],tp,jla[maxn],jlb[maxn];
struct asd{
	int nx,ny;
	asd(){}
	asd(int aa,int bb){
		nx=aa,ny=bb;
	}
}b[maxn];
void xg(int nx,int ny){
	if(nx<1 || ny<1 || nx>n || ny>m) return;
	if(vis[id[nx][ny]]) return;
	if(s[id[nx][ny]]==0) return;
	js[id[nx][ny]]--;
	if(!inq[id[nx][ny]]){
		sta[++tp]=id[nx][ny];
		inq[id[nx][ny]]=1;
	}
}
int fa[maxn];
int zhao(int xx){
	if(fa[xx]==xx) return xx;
	return fa[xx]=zhao(fa[xx]);
}
int main(){
    freopen("t_covering.in","r",stdin);
	freopen("t_covering.out","w",stdout);
	memset(zxz,0x3f,sizeof(zxz));
	n=read(),m=read();
	rg int aa,bb;
	for(rg int i=1;i<=n;i++){
		a[i].push_back(0);
		id[i].push_back(0);
		for(rg int j=1;j<=m;j++){
			aa=read();
			a[i].push_back(aa);
			cnt++;
			id[i].push_back(cnt);
		}
	}
	k=read();
	if(k*4>n*m){
		printf("No\n");
		for(rg int i=1;i<=k;i++){
			aa=read(),bb=read();
		}
		return 0;
	}
	for(rg int i=1;i<=k;i++){
		aa=read(),bb=read();
		aa++,bb++;
		if(s[id[aa][bb]]==1){
			jud=1;
		}
		b[i].nx=aa,b[i].ny=bb;
		jla[id[aa][bb]]=aa,jlb[id[aa][bb]]=bb;
		s[id[aa][bb]]=1;
	}
	if(k){
		if(n==1 || m==1) jud=1;
	}
	if(jud){
		printf("No\n");
		return 0;
	}
	for(rg int i=1;i<=k;i++){
		js[id[b[i].nx][b[i].ny]]=4;
	}
	for(rg int i=1;i<=k;i++){
		aa=b[i].nx,bb=b[i].ny;
		if((aa==1 || aa==n) && (bb==1 || bb==m)){
			printf("No\n");
			return 0;
		}
		if(aa==1){
			vis[id[aa][bb]]=1;
			if(haha[id[aa][bb]] || haha[id[aa][bb-1]] || haha[id[aa][bb+1]] || haha[id[aa+1][bb]]){
				printf("No\n");
				return 0;
			}
			xg(aa,bb+2);
			xg(aa,bb-2);
			xg(aa+2,bb);
			haha[id[aa][bb]]=haha[id[aa][bb-1]]=haha[id[aa][bb+1]]=haha[id[aa+1][bb]]=1;
			ans+=a[aa][bb-1]+a[aa][bb+1]+a[aa+1][bb]+a[aa][bb];
		} else if(aa==n){
			vis[id[aa][bb]]=1;
			if(haha[id[aa][bb]] || haha[id[aa][bb-1]] || haha[id[aa][bb+1]] || haha[id[aa-1][bb]]){
				printf("No\n");
				return 0;
			}
			xg(aa,bb+2);
			xg(aa,bb-2);
			xg(aa-2,bb);
			haha[id[aa][bb]]=haha[id[aa][bb-1]]=haha[id[aa][bb+1]]=haha[id[aa-1][bb]]=1;
			ans+=a[aa][bb-1]+a[aa][bb+1]+a[aa-1][bb]+a[aa][bb];
		} else if(bb==1){
			vis[id[aa][bb]]=1;
			if(haha[id[aa][bb]] || haha[id[aa-1][bb]] || haha[id[aa+1][bb]] || haha[id[aa][bb+1]]){
				printf("No\n");
				return 0;
			}
			xg(aa-2,bb);
			xg(aa+2,bb);
			xg(aa,bb+2);
			haha[id[aa][bb]]=haha[id[aa-1][bb]]=haha[id[aa+1][bb]]=haha[id[aa][bb+1]]=1;
			ans+=a[aa-1][bb]+a[aa+1][bb]+a[aa][bb+1]+a[aa][bb];
		} else if(bb==m){
			vis[id[aa][bb]]=1;
			if(haha[id[aa][bb]] || haha[id[aa-1][bb]] || haha[id[aa+1][bb]] || haha[id[aa][bb-1]]){
				printf("No\n");
				return 0;
			}
			xg(aa-2,bb);
			xg(aa+2,bb);
			xg(aa,bb-2);
			haha[id[aa][bb]]=haha[id[aa-1][bb]]=haha[id[aa+1][bb]]=haha[id[aa][bb-1]]=1;
			ans+=a[aa-1][bb]+a[aa+1][bb]+a[aa][bb-1]+a[aa][bb];
		}
	}
	rg int mx,my;
	for(rg int i=1;i<=k;i++){
		aa=b[i].nx,bb=b[i].ny;
		if(aa+1<=n){
			mx=aa+1,my=bb;
			if(s[id[mx][my]]){
				if(!vis[id[mx][my]]){
					vis[id[mx][my]]=1;
					if(haha[id[mx][my+1]] || haha[id[mx][my-1]] || haha[id[mx+1][my]] || haha[id[mx][my]]){
						printf("No\n");
						return 0;
					}
					xg(mx,my+2);
					xg(mx,my-2);
					xg(mx+2,my);
					haha[id[mx][my+1]]=haha[id[mx][my-1]]=haha[id[mx+1][my]]=haha[id[mx][my]]=1;
					ans+=a[mx][my+1]+a[mx][my-1]+a[mx+1][my]+a[mx][my];
				}
				if(!vis[id[aa][bb]]){
					vis[id[aa][bb]]=1;
					if(haha[id[aa][bb-1]] || haha[id[aa][bb+1]] || haha[id[aa-1][bb]] || haha[id[aa][bb]]){
						printf("No\n");
						return 0;
					}
					xg(aa,bb-2);
					xg(aa,bb+2);
					xg(aa-2,bb);
					haha[id[aa][bb-1]]=haha[id[aa][bb+1]]=haha[id[aa-1][bb]]=haha[id[aa][bb]]=1;
					ans+=a[aa][bb-1]+a[aa][bb+1]+a[aa-1][bb]+a[aa][bb];
					vis[id[aa][bb]]=1;
				}
			}
		}
		if(bb+1<=m){
			mx=aa,my=bb+1;
			if(s[id[mx][my]]){
				if(!vis[id[mx][my]]){
					vis[id[mx][my]]=1;
					if(haha[id[mx+1][my]] || haha[id[mx-1][my]] || haha[id[mx][my+1]] || haha[id[mx][my]]){
						printf("No\n");
						return 0;
					}
					xg(mx-2,my);
					xg(mx+2,my);
					xg(mx,my+2);
					haha[id[mx+1][my]]=haha[id[mx-1][my]]=haha[id[mx][my+1]]=haha[id[mx][my]]=1;
					ans+=a[mx+1][my]+a[mx-1][my]+a[mx][my+1]+a[mx][my];
				}
				if(!vis[id[aa][bb]]){
					vis[id[aa][bb]]=1;
					if(haha[id[aa-1][bb]] || haha[id[aa+1][bb]] || haha[id[aa][bb-1]] || haha[id[aa][bb]]){
						printf("No\n");
						return 0;
					}
					xg(aa-2,bb);
					xg(aa+2,bb);
					xg(aa,bb-2);
					haha[id[aa-1][bb]]=haha[id[aa+1][bb]]=haha[id[aa][bb-1]]=haha[id[aa][bb]]=1;
					ans+=a[aa-1][bb]+a[aa+1][bb]+a[aa][bb-1]+a[aa][bb];
					vis[id[aa][bb]]=1;
				}
			}
		}
	}
	for(rg int i=1;i<=k;i++){
		aa=b[i].nx,bb=b[i].ny;
		if(aa+1<=n && bb+1<=m){
			mx=aa+1,my=bb+1;
			if(s[id[mx][my]]){
				if(!vis[id[mx][my]]){
					vis[id[mx][my]]=1;
					if(haha[id[mx+1][my]] || haha[id[mx-1][my]] || haha[id[mx][my+1]] || haha[id[mx][my]]){
						printf("No\n");
						return 0;
					}
					xg(mx-2,my);
					xg(mx+2,my);
					xg(mx,my+2);
					haha[id[mx+1][my]]=haha[id[mx-1][my]]=haha[id[mx][my+1]]=haha[id[mx][my]]=1;
					ans+=a[mx+1][my]+a[mx-1][my]+a[mx][my+1]+a[mx][my];
				}
				if(!vis[id[aa][bb]]){
					vis[id[aa][bb]]=1;
					if(haha[id[aa+1][bb]] || haha[id[aa-1][bb]] || haha[id[aa][bb-1]] || haha[id[aa][bb]]){
						printf("No\n");
						return 0;
					}
					xg(aa-2,bb);
					xg(aa+2,bb);
					xg(aa,bb-2);
					haha[id[aa+1][bb]]=haha[id[aa-1][bb]]=haha[id[aa][bb-1]]=haha[id[aa][bb]]=1;
					ans+=a[aa+1][bb]+a[aa-1][bb]+a[aa][bb-1]+a[aa][bb];
					vis[id[aa][bb]]=1;
				}
			}
		}
		if(bb-1>=1 && aa+1<=n){
			mx=aa+1,my=bb-1;
			if(s[id[mx][my]]){
				if(!vis[id[mx][my]]){
					vis[id[mx][my]]=1;
					if(haha[id[mx+1][my]] || haha[id[mx-1][my]] || haha[id[mx][my-1]] || haha[id[mx][my]]){
						printf("No\n");
						return 0;
					}
					xg(mx-2,my);
					xg(mx+2,my);
					xg(mx,my-2);
					haha[id[mx+1][my]]=haha[id[mx-1][my]]=haha[id[mx][my-1]]=haha[id[mx][my]]=1;
					ans+=a[mx+1][my]+a[mx-1][my]+a[mx][my-1]+a[mx][my];
				}
				if(!vis[id[aa][bb]]){
					vis[id[aa][bb]]=1;
					if(haha[id[aa+1][bb]] || haha[id[aa-1][bb]] || haha[id[aa][bb+1]] || haha[id[aa][bb]]){
						printf("No\n");
						return 0;
					}
					xg(aa-2,bb);
					xg(aa+2,bb);
					xg(aa,bb+2);
					haha[id[aa+1][bb]]=haha[id[aa-1][bb]]=haha[id[aa][bb+1]]=haha[id[aa][bb]]=1;
					ans+=a[aa+1][bb]+a[aa-1][bb]+a[aa][bb+1]+a[aa][bb];
					vis[id[aa][bb]]=1;
				}
			}
		}
	}
	for(rg int i=1;i<=tp;i++){
		if(vis[sta[i]]) continue;
		if(js[sta[i]]<=2){
			printf("No\n");
			return 0;
		} else {
			mx=jla[sta[i]],my=jlb[sta[i]];
			ans+=a[mx][my+1]+a[mx][my-1]+a[mx+1][my]+a[mx-1][my]+a[mx][my];
			vis[sta[i]]=1;
			if(haha[id[mx][my+1]]){
				ans-=a[mx][my+1];
				xg(mx-2,my);
				xg(mx+2,my);
				xg(mx,my-2);
			} else if(haha[id[mx][my-1]]){
				ans-=a[mx][my-1];
				xg(mx-2,my);
				xg(mx+2,my);
				xg(mx,my+2);
			} else if(haha[id[mx-1][my]]){
				ans-=a[mx-1][my];
				xg(mx,my-2);
				xg(mx,my+2);
				xg(mx+2,my);
			} else {
				ans-=a[mx+1][my];
				xg(mx,my-2);
				xg(mx,my+2);
				xg(mx-2,my);
			}
		}
	}
	for(rg int i=1;i<=cnt;i++){
		fa[i]=i;
	}
	rg int cc,dd;
	for(rg int i=1;i<=k;i++){
		if(vis[id[b[i].nx][b[i].ny]]) continue;
		aa=b[i].nx,bb=b[i].ny;
		cc=id[b[i].nx][b[i].ny];
		tot[cc]+=a[aa][bb]+a[aa-1][bb]+a[aa+1][bb]+a[aa][bb-1]+a[aa][bb+1];
		zxz[cc]=std::min(std::min(a[aa+1][bb],a[aa-1][bb]),std::min(a[aa][bb-1],a[aa][bb+1]));
	}
	for(rg int i=1;i<=k;i++){
		if(vis[id[b[i].nx][b[i].ny]]) continue;
		aa=b[i].nx,bb=b[i].ny;
		mx=b[i].nx+2,my=b[i].ny;
		if(mx<=n && s[id[mx][my]]){
			cc=zhao(id[aa][bb]),dd=zhao(id[mx][my]);
			if(cc==dd){
				if(huan[cc]){
					printf("No\n");
					return 0;
				}
				huan[cc]=1;
				tot[cc]-=a[aa+1][bb];
				zxz[cc]=0;
			} else {
				tot[cc]+=tot[dd];
				tot[cc]-=a[aa+1][bb];
				zxz[cc]=std::min(zxz[cc],zxz[dd]);
				fa[dd]=cc;
			}
		}
		mx=b[i].nx,my=b[i].ny+2;
		if(my<=m && s[id[mx][my]]){
			cc=zhao(id[aa][bb]),dd=zhao(id[mx][my]);
			if(cc==dd){
				if(huan[cc]){
					printf("No\n");
					return 0;
				}
				huan[cc]=1;
				tot[cc]-=a[aa][bb+1];
				zxz[cc]=0;
			} else {
				tot[cc]+=tot[dd];
				tot[cc]-=a[aa][bb+1];
				zxz[cc]=std::min(zxz[cc],zxz[dd]);
				fa[dd]=cc;
			}
		}
	}
	for(rg int i=1;i<=k;i++){
		if(vis[id[b[i].nx][b[i].ny]]) continue;
		mx=b[i].nx,my=b[i].ny;
		if(fa[id[mx][my]]!=id[mx][my]) continue;
		ans+=tot[id[mx][my]]-zxz[id[mx][my]];
	}
	printf("%d\n",ans);
	return 0;
}