拔河比賽(出自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;}