在这个问题用到了动态规划,先在主程序的外面创建两个数组a和dp,分别储存n个猴子的力量值和猴子在某一个的最大力量值,和一个变量mmin,用于两队的猴子的力量值的差。
int a[22],mmin = 10000000,dp[100000];
在main函数中创建n(猴子数量)和sum(力量值总和)。
int n,sum = 0;
cin >> n;
用for循环输入a[i],sum加上a[i],表示这n只猴子的力量值总和。
for(int i = 1;i <= n;i++){
cin >> a[i];
sum += a[i];
}
在输入之后,难点来了——将分队问题转换成背包问题(01问题)。把背包的容量看成sum/2,在平均分之后两边中最小的数就成了背包的容量;猴子的力量值就是背包问题中的重量(w)和价值(c)。
然后双重循环判断加入一只猴子的力量值和保留之前的力量值的大小,如果会超,那就保留。
for(int i = 1;i <= n;i++){
for(int j = sum/2;j >= a[i];j--){
dp[j] = max(dp[j],dp[j - a[i]] + a[i]);
}
}
最后,在循环外面,找出两边力量值差值最小的数输出。
mmin = sum - dp[sum/2] * 2;
cout << mmin;
易错(难点):
在写这个程序时,比较简单的方法就是把这个问题改变一下思路,从分队的问题变成背包问题,这样对于只会做背包问题的人来说会更加简单。如果在题目中没有“容量”、“价值”和“重量”,那就在题目中找出这三个被隐藏的数。
心得:
这个问题拿到手里时是信心满满,觉得简单,不就是动态规划吗,一步一步地写,那成功不是信手拈来。但在做的时候才发现,没有容量、价值和重量。所以在老师讲完之后,才知道把不会的题通过转换可以改成我之前学过的知识,从而更简单地去做题目。