dp专题-简单基础dp-背包

按照这个做的:http://doc.okbase.net/cc_again/archive/71796.html

hdu 1864 最大报销额 01背包

方法一:

double类型的背包

总数30个、每个最大1000、保留2位有效位。直接把double*100转换为int型的背包

代码

//看清题目
//double型的01背包
#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
using namespace std;

const int N = 3000050;
int dp[N];
int a[N];

int main(void)
{
    double total;
    int n;
    int i, j;
    while(scanf("%lf%d", &total, &n), n)
    {
        int tmp;
        int cnt = 0;
        memset(dp, 0, sizeof(dp));
        for(j = 0; j < n; j++)
        {
            scanf("%d", &tmp);
//            cin >> tmp;
            double pricetotal = 0.0;
            char c, cc;
            double price;
            int flag = 1;
            double A, B, C;
            A = B = C = 0;
            for(i = 0; i < tmp; i++)
            {
                char c;
                getchar();
                scanf("%c:%lf", &c, &price);
                if(c == 'A' && A+price <= 600.0)
                {
                    A  += price;
                }
                else if(c == 'B' && B+price <= 600.0)
                {
                    B += price;
                }
                else if(c == 'C' && C+price <= 600.0)
                {
                    C += price;
                }
                else
                    flag = 0;
            }

            if(flag && A+B+C <= 1000.0)
                a[cnt++] = (A+B+C)*100;

        }
        int v = (total)*100;
        for(i = 0; i < cnt; i++)
        {
            for(j = v; j >= a[i]; j--)
            {
                dp[j] = max(dp[j], dp[j-a[i]]+a[i]);
            }
        }
        double ans = dp[v];
        printf("%.2lf\n", ans/100.0);
    }
    return 0;
}

     
     
    
    
   
   


对个数背包,dp[j] = max(dp[j], dp[j-1]+a[i]);

网上的代码能ac但错了的代码,有后效性

这组就过不了

100.00 5
1 A:5
1 B:20
1 C:24
1 A:30
1 A:60

#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
using namespace std;

const int N = 100;
double a[N];
double dp[N];

void debug(int n, double a[])
{
    for(int i = 0; i < n; i++)
    {
        printf("%.2lf  ", a[i]);
    }
    printf("\n");
}

int main(void)
{
    double total;
    int n;
    while(~scanf("%lf%d", &total, &n), n)
    {
        int i, j;
        int cnt = 0;
        memset(a, 0, sizeof(a));
        memset(dp, 0, sizeof(dp));
        for(i = 0; i < n; i++)
        {
            int tmp  = 0;
            int flag = 1;
            scanf("%d", &tmp);
            char c;
            double price;
            double A, B, C;//三类的总价格
            A = B = C = 0;
            while(tmp--)
            {
                getchar();
                scanf("%c:%lf", &c, &price);
                if(c == 'A' && price+A <= 600.0)
                {
                    A += price;
                }
                else if(c == 'B' && price+B <= 600.0)
                {
                    B += price;
                }
                else if(c == 'C' && price+C <= 600.0)
                {
                    C += price;
                }
                else
                    flag = 0;
            }
            if(flag && A+B+C <= 1000.0)
            {
                a[cnt++] = A+B+C;
            }
        }
        for(i = 0; i < cnt; i++)
        {
            for(j = cnt; j >= 1; j--)
            {
                if(dp[j-1]+a[i] <= total)
                    dp[j] = max(dp[j], dp[j-1]+a[i]);
            }
        }
        double ans = 0;
        for(i = 0; i <= cnt; i++)
            ans = max(ans, dp[i]);
        printf("%.2lf\n", ans);
    }

    return 0;
}

     
     
    
    
   
   

方法二:
搜索

//dfs+剪枝
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
using namespace std;

const int N = 100;
double a[N];
double sum[N];

double dfs(double total, int cnt)
{
    double ans;
    if(cnt == 1) return a[cnt]>total?0:a[cnt];
    if(total >= sum[cnt]) return sum[cnt];//剪枝关键,否者时间复杂度为O(2^n)

    if(a[cnt] == total) ans = a[cnt];
    else if(a[cnt] < total)
    {
        ans = max(dfs(total-a[cnt], cnt-1)+a[cnt], dfs(total, cnt-1));
    }
    else
        ans = dfs(total, cnt-1);
    return  ans;
}

int main(void)
{
    double total;
    int n;
    int i, j;
    while(scanf("%lf%d", &total, &n), n)
    {
        int tmp;
        int cnt = 1;
        memset(sum, 0, sizeof(sum));

        for(j = 0; j < n; j++)
        {
            scanf("%d", &tmp);
            double pricetotal = 0.0;
            char c, cc;
            double price;
            int flag = 1;
            double A, B, C;
            A = B = C = 0;
            for(i = 0; i < tmp; i++)
            {
                char c;
                getchar();
                scanf("%c:%lf", &c, &price);
                if(c == 'A' && A+price <= 600.0)
                {
                    A  += price;
                }
                else if(c == 'B' && B+price <= 600.0)
                {
                    B += price;
                }
                else if(c == 'C' && C+price <= 600.0)
                {
                    C += price;
                }
                else
                    flag = 0;
            }

            if(flag && A+B+C <= 1000.0)
                a[cnt++] = (A+B+C);
        }
        for(i = 1; i < cnt; i++)
        {
            sum[i] = sum[i-1] + a[i];
        }
        printf("%.2lf\n", dfs(total, cnt-1));
    }
    return 0;
}

      
      
     
     
    
    






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值