您的位置:首页 > 其它

poj 2576 dp背包/随机交换(体重均分)

2015-02-07 16:14 302 查看
题意:有n个人,每个人一个体重值。要求把这两个人平均分成两部分,使得两部分的体重之和的差最小。

思路:1、背包dp。把所有人总重量的一半当做value上限,背包限重为(n+1)/2,求最接近value的值。

2、随机化.。随机分成两组,然后随机交换。其中对于随机的实验组数,亲测245次WA,250次AC。细节见注释

#include <stdio.h>
#include <string.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define N 102
int n,m,v
,dp[45005>>1];
int main(){
int i,j,sum=0;
memset(dp, 0, sizeof(dp));
scanf("%d",&n);
for(i = 1;i<=n;i++){
scanf("%d",&v[i]);
sum += v[i];
}
m = (n+1)/2;
dp[0] = 1;
for(i = 1;i<=n;i++){
for(j = sum/2;j>=0;j--){
if(dp[j] && dp[j]<=m && dp[j+v[i]]<=sum/2){
if(!dp[j+v[i]])
dp[j+v[i]] = dp[j]+1;
else
dp[j+v[i]] = min(dp[j+v[i]],dp[j]+1);
}
}
}
for(i = sum/2;i>=0;i--)
if(dp[i]){
printf("%d %d\n",i,sum-i);
break;
}
return 0;
}


随机代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define N 102
int n,m,a
,s
,t
;
int main(){
int i,j,sum,s1,s2,T=250,temp1,temp2,len1,len2,flag,res1=0;//T是随机的实验组数,亲测245WA,250AC
s1 = s2 = sum = 0;
scanf("%d",&n);
for(i = 0;i<n;i++){
scanf("%d",&a[i]);
sum += a[i];
}
if(n==1){
printf("0 %d\n",a[0]);
return 0;
}
m = n - n/2;
n /= 2;
while(T--){
len1 = len2 = flag = s1 = s2 = 0;
for(i = 0;len1<n && len2<m;i++){//将数据随机分成两份
if(rand()%2){
t[len2++] = a[i];
s2 += a[i];
}
else{
s[len1++] = a[i];
s1 += a[i];
}
}
while(len1 < n){
s1 += a[i];
s[len1++] = a[i++];
}
while(len2 < m){
s2 += a[i];
t[len2++] = a[i++];
}
while(flag<10){
i = rand()%n;//在两份数据中任选一个进行调换
j = rand()%m;
temp1 = abs(s1 - s2);
temp2 = abs(s1 - s2 - 2*(s[i]-t[j]));
if(temp1 > temp2){//如果调换结果更好,那么进行调换
flag = 0;
s1 -= s[i]-t[j];
s2 -= t[j]-s[i];
temp1 = s[i];
s[i] = t[j];
t[j] = temp1;
}
flag++;//flag保存有多少次没有进行过更新了
}
res1 = max(res1,min(s1,s2));
}
printf("%d %d\n",res1,sum-res1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: