zoukankan      html  css  js  c++  java
  • [Usaco2013 Nov]No Change

    Description
    Farmer John is at the market to purchase supplies for his farm. He has in his pocket K coins (1 <= K <= 16), each with value in the range 1..100,000,000. FJ would like to make a sequence of N purchases (1 <= N <= 100,000), where the ith purchase costs c(i) units of money (1 <= c(i) <= 10,000). As he makes this sequence of purchases, he can periodically stop and pay, with a single coin, for all the purchases made since his last payment (of course, the single coin he uses must be large enough to pay for all of these). Unfortunately, the vendors at the market are completely out of change, so whenever FJ uses a coin that is larger than the amount of money he owes, he sadly receives no changes in return! Please compute the maximum amount of money FJ can end up with after making his N purchases in sequence. Output -1 if it is impossible for FJ to make all of his purchases.

    K个硬币,要买N个物品。
    给定买的顺序,即按顺序必须是一路买过去,当选定买的东西物品序列后,付出钱后,货主是不会找零钱的。
    现希望买完所需要的东西后,留下的钱越多越好,如果不能完成购买任务,输出-1

    Input

    • Line 1: Two integers, K and N.
    • Lines 2..1+K: Each line contains the amount of money of one of FJ's coins.
    • Lines 2+K..1+N+K: These N lines contain the costs of FJ's intended purchases.

    Output

    • Line 1: The maximum amount of money FJ can end up with, or -1 if FJ cannot complete all of his purchases.

    Sample Input
    3 6
    12
    15
    10
    6
    3
    3
    2
    3
    7

    Sample Output
    12


    按顺序来这一点保证了我们能够对一枚硬币买到的东西一定是一段区间,那么我们就可以找到一个起始点来二分查找结束点。设F[sta]表示使用的硬币状态为sta,所能买到的最多的物品个数,每次转移时枚举一个没用过的硬币,从F[sta]开始向后买尽可能多的东西,结束点可以使用二分来找到。

    (F[sta|(1<<(i-1))]=max(F[sta|(1<<(i-1))],find(F[sta],coin[i]));)

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x>=10)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e5;
    int val[N+10],sum[N+10];
    int f[(1<<17)+10],A[20];
    int limit;
    int find(int x,int k){
    	k+=sum[x];
    	int l=x+1,r=limit;
    	while (l<=r){
    		int mid=(l+r)>>1;
    		if (k<sum[mid])	r=mid-1;
    		else	l=mid+1;
    	}
    	return l-1;
    }
    int main(){
    	int k=read(),n=read(),Ans=-inf; limit=n;
    	for (int i=1;i<=k;i++)	A[i]=read();
    	for (int i=1;i<=n;i++)	sum[i]=sum[i-1]+(val[i]=read());
    	memset(f,255,sizeof(f));
    	f[0]=0;
    	for (int sta=0;sta<1<<k;sta++){
    		if (f[sta]==-1)	continue;
    		if (f[sta]==n){
    			int res=0;
    			for (int i=1;i<=k;i++)	if (!(sta&(1<<(i-1))))	res+=A[i];
    			Ans=max(Ans,res);
    		}
    		for (int i=1;i<=k;i++){
    			if (sta&(1<<(i-1)))	continue;
    			f[sta|(1<<(i-1))]=max(f[sta|(1<<(i-1))],find(f[sta],A[i]));
    		}
    	}
    	printf("%d
    ",Ans==-inf?-1:Ans);
    	return 0;
    }
    
  • 相关阅读:
    javaWeb css图文混排
    Junit 测试 @Test 红名问题
    java面试题:已知一个数组[2,4,6,2,1,5],将该数组进行排序(降序,不能用工具类进行排序),创建两条线程交替输出排序后的数组,线程名自定义
    【转】正则表达式的分组
    正则表达式基础
    IIS连接数修改
    【整理】fiddler不能监听 localhost和 127.0.0.1的问题
    【转】WKT、SRID、EPSG概念
    WPF中查找控件的扩展类
    【转】告别码农,成为真正的程序员
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/9656718.html
Copyright © 2011-2022 走看看