• 买瓜(dfs+剪枝)


    题目描述

    小蓝正在一个瓜摊上买瓜。瓜摊上共有 n 个瓜,每个瓜的重量为 Ai 。

    小蓝刀功了得,他可以把任何瓜劈成完全等重的两份,不过每个瓜只能劈一刀。

    小蓝希望买到的瓜的重量的和恰好为 m 。

    请问小蓝至少要劈多少个瓜才能买到重量恰好为 m 的瓜。如果无论怎样小蓝都无法得到总重恰好为 m 的瓜,请输出 −1 。

    输入格式

    输入的第一行包含两个整数 n, m,用一个空格分隔,分别表示瓜的个数和小蓝想买到的瓜的总重量。

    第二行包含 n 个整数 Ai,相邻整数之间使用一个空格分隔,分别表示每个瓜的重量。

    输出格式

    输出一行包含一个整数表示答案。

    样例输入

    3 10
    1 3 13

    样例输出

    2

    提示

    对于 20% 的评测用例,∑n≤10;

    对于 60% 的评测用例,∑n≤20;

    对于所有评测用例,1 ≤n≤30,1≤ Ai ≤ 10^9 ,1 ≤ m ≤ 10^9

    思路:

    使用深度优先搜索解决, 对每个瓜的三种选择进行搜索, 解空间树是一颗完全三叉树, 时间复杂度为O(3^n), 肯定会超时, 故需要进行剪枝。

    买半个瓜时需要将重量除2,会产生小数,故可以将重量数组都乘2,最大重量也乘2。

    搜索时需要记录三个状态,当前层数pos,当前总重量sum,当前劈瓜的次数cnt,以下情况需要剪枝:
    1)当前劈瓜次数大于已求得的最小次数,即cnt>ans
    2)当前重量之和大于要求的重量,即sum>m

    但是这样仍然会超时,还可以将重量数组降序排列,使得更快剪枝。还可以创建一个重量数组的后缀数组suf,这样在搜索时可以利用其剪枝:若当前重量加上剩余的所有瓜重量之和小于要求的重量,剪枝。

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. typedef long long ll;
    6. const int N=33;
    7. double a[N];
    8. double s[N];
    9. bool st[N];
    10. int n;
    11. double m;
    12. int cnt=1e9;
    13. //三种状态 整个 一半 不要
    14. //dfs+剪枝
    15. //参数 当前层数 当前的西瓜的总重量 当前切了多少次
    16. void dfs(int pos,double sum,int num)
    17. {
    18. //当sum==m时 取最小的 返回上一层
    19. if(sum==m)
    20. {
    21. cnt=min(cnt,num);
    22. return ;
    23. }
    24. //剪枝 sum+s[n]-s[pos-1] 是求当前sum加上之后所有的数均不能组成时 剪枝一下
    25. if(sum>m||pos>n||cnt<=num||sum+s[n]-s[pos-1]return ;
    26. dfs(pos+1,sum+a[pos],num);//整个要
    27. dfs(pos+1,sum+(a[pos]/2),num+1);//半个
    28. dfs(pos+1,sum,num);//都不要
    29. }
    30. //从大到小排 尽量减少切一半的次数
    31. double cmp(double x,double y)
    32. {
    33. return x>y;
    34. }
    35. int main()
    36. {
    37. cin>>n>>m;
    38. for(int i=1;i<=n;i++)
    39. {
    40. cin>>a[i];
    41. }
    42. //排序 从大到小排
    43. sort(a+1,a+1+n,cmp);
    44. //求前缀和
    45. for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
    46. dfs(1,0,0);
    47. if(cnt==1e9) cout<<"-1"<
    48. else cout<
    49. return 0;
    50. }

     

  • 相关阅读:
    pytest
    2023年【金属非金属矿山(地下矿山)安全管理人员】实操考试视频及金属非金属矿山(地下矿山)安全管理人员操作证考试
    建模杂谈系列156 一个接口服务的改版升级
    前端如何处理后端一次性传来的10w条数据
    行业春寒回暖,持续承压的酒店企业于何处破局?
    WPF 项目开发入门(八)数据库驱动配置与数据库操作
    SQL获取IP电脑名
    本是同根生-双数据库集群keepalived virtual_route_id冲突导致连接故障
    [Games101] Lecture 05 Rasterization 1 (Triangles)
    JVM堆内存的结构,YGC,FGC的原理
  • 原文地址:https://blog.csdn.net/m0_74015873/article/details/136566318