回溯

/*      1)回溯的基本思想:回溯就是优化的枚举,
            运用的是试探的思想,在试探的过程
            中,一旦发现原来的选择是错误的,
            那么就退回一步重新选择,然后继续
            向前试探,反复这样的过程直到求解
            出问题的解.
        2)回溯的两个要素:
            1.dfs
            2.剪枝
        3)回溯算法的基本步骤:
            1.画解空间树
            2.设计Cutting函数:CUtting函数有两个分类:
                    第一个:约束函数:即不满足约束条
                        件,比如01背包问题中的背包装不下了
                    第二个:限界函数:即这条路走了,没
                        有走另外一条路好,少年,回头吧,走
                        另外一条路*/
/*01背包:给定n种物品和一背包。物品i的重量是wi>0,其价值为vi>0,
背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中物品
的总价值最大? */
/*#include <iostream>
using namespace std;
int ans=0,sum=0,mmm=0;
int n,v;//n为数目,v为容量
int c[110],w[110];//c为价格,w为重量
void dfs(int step);
int main()
{
    cin>>n>>v;
    for(int i=0;i<n;i++)
        cin>>c[i]>>w[i];
    dfs(0);
    cout<<mmm<<endl;
    return 0;
}
void dfs(int step)
{
    if(step==n)
    {
        if(sum>mmm) mmm=sum;
        return ;
    }
    else
    {
        if(ans+w[step]<v)
        {
            sum=sum+c[step];
            ans=ans+w[step];
            dfs(step+1);
            sum=sum-c[step];
            ans=ans-w[step];
        }
        else step++;
    }
}*/
/*
输入:
5 10
6 2
3 2
6 4
5 6
4 5
输出:
1 1 1 0 0 放入背包的物品重量为:8 价值为:15
*/
#include<bits/stdc++.h>
using namespace std;
#define max_v 105
int n;
int v[max_v],w[max_v];
int c;//背包容量
int cv=0;//当前装的物品的总价值
int cw=0;//当前装的物品的总重量
int bestv=0;//最优总价值
int bestx[max_v];//最优解
int x[max_v]={0};//当前解
int bound(int i)
{
    int l=c-cw;
    int b=cv;
    while(w[i]<=l&&i<=n)
    {
        b+=v[i];
        l-=w[i];
        i++;
    }
    if(i<=n)
        b+=l*v[i]/w[i];
    return b;

}
void dfs(int i)
{
    if(i>n)//搜完了一条路
    {
        for(int j=1;j<=n;j++)
            bestx[j]=x[j];
        bestv=cv;
    }else
    {
        if(cw+w[i]<=c)//装得下
        {
            x[i]=1;//该物品装
            cw+=w[i];
            cv+=v[i];

            dfs(i+1);//搜索下一个物品

            x[i]=0;//回退
            cw-=w[i];
            cv-=v[i];
        }
        if(bound(i+1)>bestv)//最优总价值小于上界,当前已经选了的物品的总价值加上该物品后面可以装的物品的价值大于最优总价值,那么当前物品就没有必要装
        {
            x[i]=0;
            dfs(i+1);
        }
    }

}
void putout()
{
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        printf("%d ",bestx[i]);
        if(bestx[i]==1)
        sum+=w[i];
    }
    printf("放入背包的物品重量为:%d 价值为:%d",sum,bestv);
}
int main()
{
    scanf("%d %d",&n,&c);
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d",&v[i],&w[i]);
    }
    dfs(1);
    putout();
    return 0;
}
/*
输入:
5 10
6 2
3 2
6 4
5 6
4 5
输出:
1 1 1 0 0 放入背包的物品重量为:8 价值为:15
*/
/*#include <iostream>
using namespace std;
int n;
int a[10][10];
int b[10]={0},c[10]={0},d[10]={0};
int main()
{
    cin>>n;
    memset(a,0sizeof(a));
    return 0;
}
void dfs(int step)
{
    for(int i=0;i<n;i++)
    {
        if()
    }
}*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值