zoukankan      html  css  js  c++  java
  • F. Shovels Shop 背包DP

    题意:  

    商店里有n把铲子 每个铲子有其标价

    一个人要买k吧

    有m个优惠政策

    每个优惠政策有两个元素x,y

    表示   正好买x个铲子的时候  这x个铲子中最便宜的y个铲子免单

    求用最少的前买到k个铲子

    显然  将n个铲子升序排序好  取前k个  剩下的和本题无关!!

    然后前缀和  方便求区间的价值和  

    要求最少的钱  其实可以转化为求最大的优惠数额

    到这一步大致可以看出是一个背包问题了 

    每个优惠政策可以无限次使用  所以是一个完全背包

    即使每次价值都随着容量改变  也可以用背包法来做 

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    #define N 200000+5
    
    int a[N];
    ll dp[N];
    ll sum[N];
    int v[N];
    int c[N];
    
    int main()
    {
        int n,m,k;
        RIII(n,m,k);
        rep(i,1,n)
        RI(a[i]);
        sort(a+1,a+1+n);
    
        rep(i,1,n)
        sum[i]=sum[i-1]+a[i];
        rep(i,1,m)
        RII(v[i],c[i]);
    
        rep(j,1,k)
        rep(i,1,m)
        if(j>=v[i])
        dp[j]=max(dp[j],dp[j-v[i]]+sum[j-v[i]+c[i]]-sum[j-v[i]]);
        cout<<sum[k]-dp[k];
    
        return 0;
    }
    View Code

    将背包的两个for循环顺序交换一下就会wa ?因为这种顺序是只取只取一个  (优惠一次一次只能用一种) 为分组背包!

    更加简便的题解:

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> P;
    const int maxn=2e5+10;
    const int maxk=2e3+10;
    
    int n,m,k;
    int a[maxn],s[maxn];
    int g[maxk];
    int f[maxk];
    
    int main()
    {
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            if(x<=k) g[x]=max(g[x],y);
        }
        sort(a+1,a+n+1);
        for(int i=1;i<=k;i++) s[i]=s[i-1]+a[i];
        for(int i=1;i<=k;i++)
        {
            f[i]=0;
            for(int j=0;j<i;j++)
                f[i]=max(f[i],f[j]+s[j+g[i-j]]-s[j]);
        }
        cout<<s[k]-f[k]<<endl;
    }
    View Code
  • 相关阅读:
    PAT 1010. 一元多项式求导 (25)
    PAT 1009. 说反话 (20) JAVA
    PAT 1009. 说反话 (20)
    PAT 1007. 素数对猜想 (20)
    POJ 2752 Seek the Name, Seek the Fame KMP
    POJ 2406 Power Strings KMP
    ZOJ3811 Untrusted Patrol
    Codeforces Round #265 (Div. 2) 题解
    Topcoder SRM632 DIV2 解题报告
    Topcoder SRM631 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/bxd123/p/10731129.html
Copyright © 2011-2022 走看看