zoukankan      html  css  js  c++  java
  • [原创] Karen and Supermarket 2

    在回家的路上,凯伦决定到超市停下来买一些杂货。 她需要买很多东西,但因为她是学生,所以她的预算仍然很有限。

    事实上,她只花了b美元。

    超市出售N种商品。第i件商品可以以ci美元的价格购买。当然,每件商品只能买一次。

    最近,超市一直在努力促销。凯伦作为一个忠实的客户,收到了n张优惠券。

    如果凯伦购买i次商品,她可以用i次优惠券降低di美元。 当然,不买对应的商品,优惠券不能使用。

    然而,对于优惠券有一个规则。对于所有i>=2,为了使用i张优惠券,凯伦必须买第j个商品。

    凯伦想知道。她能在不超过预算B的情况下购买的最大商品数量是多少?
    输入输出样例
    输入样例#1: 复制

    6 16
    10 9
    10 5 1
    12 2 1
    20 18 3
    10 2 3
    2 1 5

    输出样例#1: 复制

    4

    Solution

    考试题目写挂,看错题了。想看原题的戳这里。树型dp,我们定义(f[i][j][2])代表i结点选了j个节点,当前节点选不选。容易想到dp方程为

    [f[x][k+j][0]=min(f[x][k+j][0],f[to][j][0]+f[x][k][0]); ]

    [f[x][k+j][0]=min(f[x][k+j][0],f[to][j][1]+f[x][k][0]); ]

    [f[x][k+j][1]=min(f[x][k+j][1],f[to][j][1]-v[to]+f[x][k][1]); ]

    [f[x][k+j][1]=min(f[x][k+j][1],f[to][j][1]+f[x][k][1]); ]

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct node
    {
        int to,next;
    }a[1000100];
    int w[101000],v[100100],len,last[101010],son[100010],tot;
    int f[5100][5100][2];
    void add(int a1,int a2)
    {
        a[++len].to=a2;
        a[len].next=last[a1];
        last[a1]=len;
    }
    void dp(int x,int father)
    {
        son[x]=1;
        for(int i=last[x];i;i=a[i].next)
        {
            int to=a[i].to;
            if(to==father)
            continue;
            dp(to,x);
            for(int k=son[x];k>=0;k--)
            for(int j=son[to];j>=0;j--)
            {
                f[x][k+j][0]=min(f[x][k+j][0],f[to][j][0]+f[x][k][0]);
                f[x][k+j][0]=min(f[x][k+j][0],f[to][j][1]+f[x][k][0]);
                f[x][k+j][1]=min(f[x][k+j][1],f[to][j][1]-v[to]+f[x][k][1]);
                f[x][k+j][1]=min(f[x][k+j][1],f[to][j][0]+f[x][k][1]);
            }
            son[x]+=son[to];
        }
    }
    int main()
    {
        //freopen("shopping.in","r",stdin);
        //freopen("shopping.out","w",stdout);
        memset(f,0x3f,sizeof(f));
        int n,s,x;
        cin>>n>>s;
        cin>>w[1]>>v[1];
        w[1]-=v[1];
        f[1][0][0]=0;f[1][1][1]=w[1];
        for(int i=2;i<=n;i++)
        {
            scanf("%d%d%d",&w[i],&v[i],&x);
            add(x,i);add(i,x);
        }
        for(int i=2;i<=n;i++)
        f[i][0][0]=0,f[i][1][1]=w[i];
        dp(1,0);
        for(int i=n;i>=0;i--)
        {
            if(f[1][i][0]<=s||f[1][i][1]<=s)
            {cout<<i;return 0;}
        }
    }
    

    博主蒟蒻,可以随意转载,但必须附上原文链接k-z-j

  • 相关阅读:
    整数转字符串
    SharePoint介绍性文章
    Disable Sharepoint 2007 show as System Account when system admin login
    通过IP地址获得主机名
    从文本文件读取信息
    数据库连接池问题[转]
    企业类库问题 public key 问题[经过自己测试]
    Google Analytics异步代码创建虚拟浏览量跟踪
    同一主机上WordPress博客更换域名简易八步骤(2)
    关于application/xwwwformurlencoded等字符编码的解释说明
  • 原文地址:https://www.cnblogs.com/kzj-pwq/p/9483673.html
Copyright © 2011-2022 走看看