$ P3092 \ [USACO13NOV] $ does not give change

\(Description\)

Surface problem
has \ (n (n <= 1e5 ) \) a goods and \ (k (k <= 16 ) \) coins, each coin denomination given commodity prices and, in order to purchase goods required, each can come up with a coin, on all purchases from the previous settlement to the present (provided that you can afford), do not give change, find the optimal solution so that the final remaining denominations and as large as possible

\(Solution\)

A simple lookBut in fact it is very simpleThe problem, he just thought out noon, afternoon, only the idea had lost this question
is really a good question drop Chi
relatively obvious is the need for the use of state coins compression
initial idea is to set up \ (dp [i] [j] \) represents the coin usage is \ (i \) when taking into account the current \ (J \) , the remaining \ (dp [i] [j] \) , do not remember, in short, there are many ideas but most can not be transferred or \ (MLE \) . Finally, I discovered that afternoon I was a fool, noting the title of a property can not give change, so we know that the use of coins when buying all the goods, and will know the rest of the denomination, so no need to use \ (dp [ i] [j] \) represents the remaining denominations.

Then Put another idea, because the topics mentioned in the order to buy, so the set \ (dp [i] \) to select the state \ (i \) to buy when the right boundary, the transfer process takes about an enumeration status Enumerate what pieces of coins, and then enumerate after buying the right boundary, testing the legality of taking \ (max \) can be. But to do so \ (O (NSK) \) , properly properly \ (TLE \) , consider pre-position each and every single coin as far as where to buy directly \ (O (Sk) \) transfer can be. The pretreatment process can be \ (O (nk) \) solution, the total complexity is acceptable.

Why For one coin, to buy back as much as possible of greed is right, or is it based on the nature of the subject, can not give change, when the coin used up no matter how many answers will buy subtracting the face value of the coin, let him buy as much as possible, it was possible to make coins province back down.

\(Code\)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define re register
#define maxn 100010
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int k,n,w[20],c[maxn],sumc[maxn],pos[maxn][20],MAX; 
int dp[maxn],val[maxn],sums,ans;
void work(int x)
{
    int r=1,l=1;
    while(r<=n)
    {
        while(sumc[r]-sumc[l-1]>w[x]) //这里注意写while,因为有可能加入一个后好几个区间都超过了面额 
        {
            pos[l][x]=r-1;
            l++;
        }
        r++;
    }
    while(sumc[r]-sumc[l-1]>w[x]) 
    {
        pos[l][x]=r-1;
        l++;
    }//调整 
    for(re int i=l;i<=n;++i) pos[i][x]=n;//注意把后面没有处理的区间解决掉 
    
}
void pre()
{
    for(re int i=0;i<=MAX;++i)
    {
        int now=i,cnt=1;
        while(now)
        {
            if(now&1) val[i]+=w[cnt];
            now>>=1,cnt++;
        }
    }
}
int main()
{
    k=read(),n=read();
    MAX=(1<<k)-1;
    for(re int i=1;i<=k;++i) w[i]=read(),sums+=w[i];
    for(re int i=1;i<=n;++i) c[i]=read(),sumc[i]=sumc[i-1]+c[i];
    for(re int i=1;i<=k;++i) 
    work(i);
    pre();
    for(re int s=0;s<=MAX;++s)
        for(re int i=1;i<=k;++i)
        {
            if(s&(1<<i-1)) continue;
            dp[s|(1<<i-1)]=max(dp[s|(1<<i-1)],pos[dp[s]+1][i]);
        }
    ans=0x3f3f3f3f;
    for(re int s=0;s<=MAX;++s)
    {
        if(dp[s]==n) ans=min(ans,val[s]);
    }
    if(ans==0x3f3f3f3f) printf("-1\n");
    else printf("%d\n",sums-ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/Liuz8848/p/11825974.html