拔河比赛(出自RQNOJ)
题目描述
superwyh的学校要举行拔河比赛,为了在赛前锻炼大家,老师决定把班里所有人分为两拨,进行拔河因为为锻炼所以为了避免其中一方的实力过强老师决定以体重来划分队伍,尽量保持两个队伍的体重差最少,因为老师对结果没兴趣,所以只告诉老师最小的体重差是多少就行了。这个受苦受累的任务就交给superwyh了,因为这两天superwyh的后背间谍sjh闹肚子了,所以只好superwyh亲自去调查每个人的体重,但是仅仅知道体重依然难以确定到底如何分配队伍,请各位oier帮助superwyh出出主意。
输入格式
第一行为人数(1<=n<=100),从第二行开始是每个人的体重(0<=m<=100)。
输出格式
最小体重差。
样例输入
4
10
23
41
12
样例输出
4
算法1:搜索:
#include <iostream>
#include <limits.h>
#include <cmath>
using namespace std;
int a[24];
int m=INT_MAX;
int k=0;
int n;
void f(int j,int sum){
if(j==n){
return;
}else if(j<n){
if(fabs(k-sum-sum) < m){
m=fabs(k-sum-sum);
}
f(j+1,sum+a[j]);
f(j+1,sum);
}
}
int main(){
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i];
k+=a[i];
}
f(0,0);
cout<<m<<endl;
m=INT_MAX;k=0;
}
return 0;
}
算法2:动态规划:
dp[i][j]表示取前i个,且总量可达j的是否
01背包问题
#include <iostream>
#include <string.h>
#include <cmath>
using namespace std;
#define max_n 1000
int a[max_n];
bool dp[max_n][max_n];
int main(){
int n,sum=0,m;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
m=sum;
sum/=2;
memset(dp,false,sizeof(dp));
for(int i=0;i<=n;i++)
dp[i][0]=true;
for(int i=1;i<=n;i++){
for(int j=1;j<=sum;j++){
if(j < a[i]){
dp[i][j]=dp[i-1][j];
}else{
dp[i][j]= (dp[i-1][j] || dp[i-1][j-a[i]]);
}
}
}
int t=0;
for(int i=0;i<=sum;i++){
if(dp[n][i]){
t=i;
}
}
cout<<fabs(m-t-t)<<endl;
return 0;}