1. 程式人生 > >國慶七天測(五)祭司

國慶七天測(五)祭司

【題意】給定n個數的取值範圍,把他們分為a,b兩組。找到一種恰當的分組使得,兩個集合的差值的絕對值的最大值最小。n,li,ri<=200 【分析】首先一個顯而易見的規律是,差值最大值一定是一個集合最大值減去另一個集合的最小值。這樣我們可以在確定集合時O(1)出解。然後二進位制列舉加玄學猴子排序就可以ac了,然而並不是正解。

考慮一種dp,定義f[i][j]為A集合中下界為i上界為j能否達到。設所有下界之和為suml,所有上界之和為sumr。B集合上下界為[suml-i,sumr-j]則差值絕對值最大值就是max(abs(suml-i-j),abs(sumr-i-j))。因為suml和sumr是常值,所以只要揹包i+j的值即可。因為suml<=i+j<=sumr,所以絕對值也可以去掉。 Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=81000;
bool f[maxn];
int a[maxn],b[maxn],n;
int main(){
	scanf("%d",&n);
	int suma=0,sumb=0;
	for(int i=1;i<=n;i++)
		scanf("%d%d",&a[i],&b[i]),suma+=a[i],
sumb+=b[i]; f[0]=1; for(int i=1;i<=n;i++){ int x=a[i]+b[i]; for(int j=40000;j>=0;j--) f[j+x]=f[j+x]|f[j]; } int ans=sumb; for(int i=0;i<=40000;i++) if(f[i]) ans=min(ans,max(sumb-i,i-suma)); printf("%d\n",ans); return 0; }