算法题总结2

1.金银岛

某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n1, n2, ... , ns,同时每个种类的金属总的价值也不同,分别为v1,v2, ..., vs。KID想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。注意到金属是可以被任意分割的,并且金属的价值和其重量成正比。

Input

第1行是测试数据的组数k,后面跟着k组输入。

每组测试数据占3行,第1行是一个正整数w (1 <= w <= 10000),表示口袋承重上限。第2行是一个正整数s (1 <= s <=100),表示金属种类。第3行有2s个正整数,分别为n1, v1, n2, v2, ... , ns, vs分别为第一种,第二种,...,第s种金属的总重量和总价值(1 <= ni <= 10000, 1 <= vi <= 10000)。

Output

k行,每行输出对应一个输入。输出应精确到小数点后2位。

Sample

InputcopyOutputcopy
2
50
4
10 100 50 30 7 34 87 100
10000
5
1 43 43 323 35 45 43 54 87 43
171.93
508.00

 代码展示

​
#include <stdio.h>
#include <stdlib.h>
struct Kuangshi {
	int weight;
	int money;
	double danjia;
};
int cmp(const void *a, const void *b) {
	struct Kuangshi *aa = (struct Kuangshi *)a;
	struct Kuangshi *bb = (struct Kuangshi *)b;
	return (((aa->danjia) < (bb->danjia)) ? 1 : -1);
}
int main() {
	int k, w, s;
	int i, j;
	double Output[100];
	scanf("%d", &k);			//组数
 
	for ( i = 0; i < k; i++) {
		scanf("%d", &w);		//口袋上限
		scanf("%d", &s);		//矿石种类
		Kuangshi kuangshi[s];
		
		for ( j = 0; j < s; j++) {	//录入
			scanf("%d %d", &kuangshi[j].weight, &kuangshi[j].money);
			kuangshi[j].danjia = (double)kuangshi[j].money / (double)kuangshi[j].weight;
		}
		qsort(kuangshi, s, sizeof(kuangshi[0]), cmp); //从大到小排序
		int shengyu = w;			//剩余空间
		j = 0;
		Output[i]=0;
		do {
			shengyu -= kuangshi[j].weight;
			if(shengyu<0){
				Output[i]=Output[i]+(shengyu+kuangshi[j].weight)*kuangshi[j].danjia;
			}else	Output[i] += kuangshi[j].money;
			j++;
 
		} while (shengyu > 0&&j<s);
 
	}
	for(int i=0;i<k;i++){
		printf("%.2lf\n",Output[i]);
	}
	return 0;
}

​

 2.田忌赛马

HJ最近迷上了一种赛马游戏,邀请你和他一起愉快的玩耍。HJ觉得只是单纯的赛马不够刺激,需要来点彩头。你如果赢了HJ,就能获得200元,当然,输了就要给HJ 200元,平局则不产生金钱交易。现在你通过|SAKURA|SC提前得知了HJ的马的实力,你需要计算出,你最多能赢得多少钱。

Input

多组输入,最多50组,当N为0时结束,不需要处理这组数据。
第一行一个N。(N <= 1000)
接下来N个数,代表你的马的战斗力。
接下来N个数,代表HJ的马的战斗力。

Output

输出你最多能赢得多少钱。(答案可能为负数)

Sample Input

3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0

Sample Output

200
0
0

代码展示 

#include<stdio.h>
#include<stdlib.h>
long a[10000],b[10000];
int cmp( const void *a, const void *b )
{
    return ( *( long *)a) - ( *( long *)b);
}

int main()
{
    long n;
    while(1)
    {
    long sum=0,i,j,end1,end2;
        scanf("%ld",&n);
        if(n==0) break;
        for(i=0;i<n;i++)
        scanf("%ld",&a[i]);
        for(i=0;i<n;i++)
            scanf("%ld",&b[i]);
        qsort( a, n, sizeof( long ), cmp );
        qsort(b, n, sizeof( long ), cmp );
        j=0;
        for(i=j=n-1,end1=end2=0;j>=end2&&i>=end1;j--)
        {
            if(a[i]>b[j])
            {
                sum++;
                i--;
            }
            else if(a[i]<b[j]){
                sum--;
				end1++;
			    }
            else
            {
                if(a[end1]>b[end2])//a最弱的马强于b最弱的马
            {
                sum++;
			    end1++;
			    end2++;
			    j++;
            }
            else if(a[end1]<b[end2])
            {
                sum--;
			    end1++;
            }
            else
            {
                if(a[end1]==b[j])
                    end1++;
                else
                {
                    sum--;
			        end1++;  
                }  
            }
            }
        }
        printf("%d\n",sum*200);
    }
    return 0;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值