翰翰和达达饲养了 N 只小猫,这天,小猫们要去爬山。 经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。 翰翰和达达只好花钱让它们坐索道下山。
索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1、C2……CN。 当然,每辆缆车上的小猫的重量之和不能超过 W。
翰翰和达达饲养了 N 只小猫,这天,小猫们要去爬山。 经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。
翰翰和达达只好花钱让它们坐索道下山。
索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1、C2……CN。 当然,每辆缆车上的小猫的重量之和不能超过 W。
每租用一辆缆车,翰翰和达达就要付 1 美元,所以他们想知道,最少需要付多少美元才能把这 N 只小猫都运送下山?
第 1 行:包含两个用空格隔开的整数,N 和 W。
第 2..N+1 行:每行一个整数,其中第 i+1 行的整数表示第 i 只小猫的重量 Ci。
输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。
输入 #1
5 1996 1 2 1994 12 29
输出 #1
2
输入 #2
7 60816099 16726954 119926 46463304 60045456 25622459 32109683 1927806
输出 #2
4
数据范围 1≤N≤18,1≤Ci≤W≤10^8
由于N的范围不太大,我们可以想到用搜索查询结果
核心代码如下:
v[1].push_back(a[1]);
开辟第一组,所以a[1]只能放入第一组
dfs(2,1);
搜索第二个数,当前组数为1
void dfs(int t,int num) 搜索第t个数字的情况,目前开辟的组数
{
if (num>ans) return ;
剪枝,如果组数已经大于最优值ans,就没有再搜的必要了
if (t==n+1)
{
已经将n个数都分好了组,接下来进行判断
if (pd(num)) ans=min(ans,num);
如果符合条件,则将ans更新为当前的组数
return ;
结束,返回上一层(必须写)
}
for (int j=1;j<=num+1;j++)
{
v[j].push_back(a[t]);
将a[t]放入第j组
dfs(t+1,max(num,j));
下一层搜索,如果j=num+1>num,表示为a[t]单独开辟一组
v[j].pop_back();
回溯,将a[t]从j组拿出,重新放进别的组
}
}
判断当前分的数是否满足条件:
bool pd(int m)
{
判断当前分组是否满足条件
for (int i=1;i<=m;i++)
{
查看第i组
int len=v[i].size();
len记录当前i组有多少个数
long long num=0;
当前组元素的总和/总质量
for (int j=0;jW) return false;
不满足,返回false(假)
}
}
return true;
满足条件,返回true(真)
}
完整代码如下:
#include
using namespace std;
int n,ans=18;
long long W;
vector v[20];
long long a[20];
bool pd(int m)
{
for (int i=1;i<=m;i++)
{
int len=v[i].size();
long long num=0;
for (int j=0;jW) return false;
}
if (num>W) return false;
}
return true;
}
void dfs(int t,int num)
{
if (num>=ans) return ;
if (t==n+1)
{
if (pd(num)) ans=min(ans,num);
return ;
}
for (int j=1;j<=num+1;j++)
{
v[j].push_back(a[t]);
dfs(t+1,max(num,j));
v[j].pop_back();
}
}
int main ()
{
int i;
cin>>n>>W;
for (i=1;i<=n;i++)
{
cin>>a[i];
}
v[1].push_back(a[1]);
dfs(2,1);
cout<
#include
using namespace std;
int n,ans=18;
long long W;
long long w[20];
vector v[20];
long long a[20];
void dfs(int t,int num)
{
if (num>=ans) return ;
if (t==n+1)
{
ans=min(ans,num);
return ;
}
for (int j=1;j<=num+1;j++)
{
v[j].push_back(a[t]);
w[j]+=a[t];
if (w[j]<=W) dfs(t+1,max(num,j));
w[j]-=a[t];
v[j].pop_back();
}
}
int main ()
{
int i;
cin>>n>>W;
for (i=1;i<=n;i++)
{
cin>>a[i];
}
w[1]+=a[1];
v[1].push_back(a[1]);
dfs(2,1);
cout<
将第j组的数放入递归中判断,可以大大减少搜索数量,并且在更新ans时不用再累加数值,可以直接更新最优解
成功Ac,完结撒花~!
如有不解或优化,可在评论区留言