翰翰和达达饲养了 NN 只小猫,这天,小猫们要去爬山。
经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。
翰翰和达达只好花钱让它们坐索道下山。
索道上的缆车最大承重量为 WW,而 NN 只小猫的重量分别是 C1、C2……CNC1、C2……CN。
当然,每辆缆车上的小猫的重量之和不能超过 WW。
每租用一辆缆车,翰翰和达达就要付 11 美元,所以他们想知道,最少需要付多少美元才能把这 NN 只小猫都运送下山?
输入格式
第 11 行:包含两个用空格隔开的整数,NN 和 WW。
第 2..N+12..N+1 行:每行一个整数,其中第 i+1i+1 行的整数表示第 ii 只小猫的重量 CiCi。
输出格式
输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。
数据范围
1≤N≤181≤N≤18,
1≤Ci≤W≤1081≤Ci≤W≤108输入样例:
5 1996 1 2 1994 12 29
输出样例:
2
首先 下面这个方法是错误的是因为:
这步是贪心,要证明正确性的。假设每辆车承重是10。下面数字均表示重量。
第一辆车开始可以放入了1, 2。
现在有第三个重量为5的小猫,你用贪心去写,那么第一辆车剩下的可以承受的重量为2,
加上省下的新开一辆车的承重是10。如果第三只小猫放入新开的一辆车,
那么第一辆车的可承受重量为7,第二辆车的可承受重量为5。如果第4,
第五只的小猫的重量分别为5和7,你用贪心就会多用了一辆车。
正是因为不能确定当前放在哪辆车上是最优解,
所以要将它枚举放在之前使用过的每一辆车和新开一辆车将他放进去这些所有可能的情况,
这是个全集,必然包含了答案总结一下就是:这个方法是只枚举当前车辆,但是小猫可能放入之前的车辆,所以这个不是正确解
错误代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20;
int w[N];
int ans;
bool st[N];
int n, weight;
void dfs(int u, int sum_weight, int start, int number)
{
if (u >= ans) return ;
if (number == n)
{
ans = u;
return ;
}
bool new_group = true;
for (int i = start; i < n; i ++ )
if (!st[i] && sum_weight + w[i] <= weight)
{
st[i] = true;
dfs(u, sum_weight + w[i], i + 1, number + 1);
st[i] = false;
new_group = false;
}
if (new_group) dfs(u + 1, 0, 0, number);
}
int main()
{
cin >> n >> weight;
for (int i = 0; i < n; i ++ ) scanf("%d", &w[i]);
sort(w, w + n);
reverse(w, w + n);
ans = n;
dfs(1, 0, 0, 0);
cout << ans << endl;
}
//正确的解题思路:从大到小枚举小猫的重量,依次枚举它可以放入之前枚举过的哪辆车内
#include <cstdio>
#include <iostream>
#include <algorithm>using namespace std;
const int N = 20;
int ans;
int w[N];
int sum[N];
int n, weight;void dfs(int u, int car)
{
if (car >= ans) return ;//若小猫车子数量大于n的返回
if (u == n) //若已经枚举完n只小猫
{
ans = car;
return ;
}
for (int i = 0; i < car; i ++ )//枚举之前枚举过的的所有车
if (sum[i] + w[u] <= weight)//若可以装入小猫,则装入小猫
{
sum[i] += w[u];
dfs(u + 1, car);
sum[i] -= w[u];
}
sum[car] = w[u];//若不能装入小猫的新开一辆车
dfs(u + 1, car + 1);
sum[car] = 0;
}int main()
{
cin >> n >> weight;
for (int i = 0; i < n; i ++ ) scanf("%d", &w[i]);
sort(w, w + n);
reverse(w, w + n);
ans = n;
dfs(0, 0);
cout << ans << endl;
return 0;
}