• [Usaco2018 Open]Talent Show


    Description
    FarmerJohn要带着他的N头奶牛,方便起见编号为1…N,到农业展览会上去,参加每年的达牛秀!他的第i头奶牛重量为wi,才艺水平为ti,两者都是整数。在到达时,FarmerJohn就被今年达牛秀的新规则吓到了:(一)参加比赛的一组奶牛必须总重量至少为W(这是为了确保是强大的队伍在比赛,而不仅是强大的某头奶牛),并且(二)总才艺值与总重量的比值最大的一组获得胜利。FJ注意到他的所有奶牛的总重量不小于W,所以他能够派出符合规则(一)的队伍。帮助他确定这样的队伍中能够达到的最佳的才艺与重量的比值。

    Input
    输入的第一行包含N和W。下面N行,每行用两个整数wi和ti描述了一头奶牛。
    1≤N≤250
    1≤W≤1000
    1≤wi≤10^6
    1≤ti≤10^3

    Output
    请求出Farmer用一组总重量最少为W的奶牛最大可能达到的总才艺值与总重量的比值。
    如果你的答案是A,输出1000A向下取整的值,以使得输出是整数(当问题中的数不是一个整数的时候,向下取整操作在向下舍入到整数的时候去除所有小数部分)。

    Sample Input
    3 15
    20 21
    10 11
    30 31

    Sample Output
    1066

    HINT
    在这个例子中,总体来看最佳的才艺与重量的比值应该是仅用一头才艺值为11、重量为10的奶牛,但是由于我们需要至少15单位的重量,最优解最终为使用这头奶牛加上才艺值为21、重量为20的奶牛。这样的话才艺与重量的比值为(11+21)/(10+20)=32/30=1.0666666...,乘以1000向下取整之后得到1066。


    首先想到dp,设f[i]代表才艺值和为i的奶牛重量,让f[i]越小越好。这样显然是错的,不过bzoj和洛谷就这么过掉了。。。(数据真水)

    放上错误dp代码

    /*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=2.5e2,M=1e3;
    int f[N*M+10];
    int main(){
    	int n=read(),W=read();
    	memset(f,127,sizeof(f));
    	f[0]=0;
    	for (int i=1;i<=n;i++){
    		int x=read(),y=read();
    		for (int j=N*M;j>=y;j--)
    			f[j]=min(f[j],f[j-y]+x);
    	}
    	int Ans=0;
    	for (int i=1;i<=N*M;i++) if (f[i]>=W)    Ans=max(Ans,i*1000/f[i]);
    	printf("%d
    ",Ans);
    	return 0;
    }
    

    后面想了想随手造了个数据把自己hack了。。。
    3 10
    7 10
    2 10
    9 10
    stdout:1818
    myout:1666

    那怎么改呢?首先我们知道这题要求(dfrac{sum t[i]}{sum w[i]})最大,我们转化一下得到(sum(t[i]-w[i] imes x)),然后x这玩意是可以二分的,直接01背包判可行性即可

    /*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=2.5e2,M=1e3;
    int f[N*M+10],w[N+10],v[N+10],n,W;
    bool check(int limit){
    	memset(f,128,sizeof(f));
    	f[0]=0;
    	for (int i=1;i<=n;i++)
    		for (int j=W;~j;j--)
    			if (f[j]!=-inf)
    				f[min(W,j+w[i])]=max(1ll*f[min(W,j+w[i])],f[j]+v[i]-1ll*w[i]*limit);
    	return f[W]>=0;
    }
    int main(){
    	n=read(),W=read();
    	int l=1,r=0,Ans=0;
    	for (int i=1;i<=n;i++)	w[i]=read(),r+=v[i]=read()*1000;
    	while (l<=r){
    		int mid=(l+r)>>1;
    		if (check(mid))	Ans=mid,l=mid+1;
    		else	r=mid-1;
    	}
    	printf("%d
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    python_day06(ip代理池)
    二叉树的层次遍历之队列的使用
    推荐系统实战笔记 1.1什么是推荐系统
    牛顿法求平方根可拓展
    java LinkedHashMap实现LRUCache缓存
    交换两个变量常规四种做法
    交换两个变量之移位交换法
    推荐系统实战笔记01--前言
    Ubuntu 14.04更新为国内阿里源解决apt-get install无法执行的问题
    求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/9626754.html
Copyright © 2020-2023  润新知