1. 程式人生 > >[USACO16FEB]圍欄Fenced In Platinum

[USACO16FEB]圍欄Fenced In Platinum

++i ans style getc 整數 pla inline 長度 nbsp

題目:洛谷P3141。

題目大意:有一個方形區域,被分成若幹區域。現在要去掉若幹條圍欄,使得所有區域連通,求最少去掉多少長度的圍欄。

解題思路:貪心。建議畫圖思考。

先對圍欄位置進行排序,然後相鄰兩條求差,再對差排序。

可以知道,每次取的是最短的一條圍欄,結果一定是最優的(橫向和豎向也要最短的優先),所以直接整行整列刪即可。

但是全刪了就會造成浪費,如果兩個塊已經連通,則不需要建邊,所以乘的時候要註意。

然後求出答案即可。具體見代碼。

註意64位整數。

C++ Code:

#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
using namespace std;
int A,B,n,m,a[25050],b[25050],x[25050],y[25050];
inline int readint(){
	char c=getchar();
	for(;!isdigit(c);c=getchar());
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^‘0‘);
	return d;
}
int main(...){
	A=readint();B=readint();n=readint();m=readint();
	for(int i=1;i<=n;++i)
	a[i]=readint();
	for(int i=1;i<=m;++i)
	b[i]=readint();
	sort(a+1,a+n+1);
	sort(b+1,b+m+1);
	a[0]=b[0]=0;
	memset(x,0x3f,sizeof x);
	memset(y,0x3f,sizeof y);
	for(int i=1;i<=n;++i)
	x[i]=a[i]-a[i-1];
	x[n+1]=A-a[n];
	for(int i=1;i<=m;++i)
	y[i]=b[i]-b[i-1];
	y[m+1]=B-b[m];
	sort(x+1,x+n+2);
	sort(y+1,y+m+2);
	long long ans=(long long)x[1]*m+(long long)y[1]*n;
	int i=2,j=2;
	for(;i<=n+1&&j<=m+1;)
	if(x[i]<y[j])ans+=(long long)x[i++]*(m-j+2);
	else ans+=(long long)y[j++]*(n-i+2);
	printf("%lld\n",ans);
	return 0;
}

[USACO16FEB]圍欄Fenced In Platinum