刷题计划

题目:多多刷题打好基础好谋更好的前路

【问题描述】

大学4个学期即将结束了,该好好规划你的专业成长的算法之路了,摆在你面前的是n道题目,第 i(1≤i≤n) 道题目能提升 ai 点能力水平值,代码量为 bi KB,无聊值为 ci ,求至少提升m点能力水平值的情况下,所做题目代码量之和的无聊值之和最小为多少。针对下面给出的样例数据,选择第1、3、4道题。

【输入】

多组测试数据。

第一行两个整数n,m(0<n≤400),接下来n行每行三个数,ai,bi,ci(0<bi,ci≤1000,0<ai≤800),其中0<m≤∑ai≤800。

【输出】

一个数,至少提升m点智力值的情况下,所做题目代码量之和∗无聊值之和的最小值。

【样例输入】

4 6

3 7 2

2 2 4

1 3 3

2 5 1

【样例输出】

90

1)题目分析:要求所选择的题目组合满足 ai相加等于m 的情况下再得到 bi相加的和与 ci相加的和的最小乘积。

将问题拆解成两个: 1.得到满足ai相加等于m的组合

                                  2.在满足1条件的组合中得到bi之和与ci之和的最小乘积

样例中:

1.可以得到ai相加等于6的组合有:      3 7 2             3 7 2

                                                             2 2 4        1 3 3

                                                             1 3 3             2 5 1

2.再计算各个组合计算出bi之和与ci之和的乘积:108 90

比较得到满足条件的最小乘积为 90

2)解题方法思路:

mi:存储当前的最小值,与新得出的乘积值比较并更新

背包问题(回溯算法):找出满足要求的各个组合

3)代码:

#include<stdio.h>
#include<stdlib.h>

int a[100001]; //存储每条轨道最后的数 

int main(){
	int n,m; //n为输入的数据个数,m做临时存储 
	int k=1; //k为轨道数,并初始化为1 
	scanf("%d\n",&n);
	scanf("%d",&m);
	a[1]=m;//初始化a[1] 
	for(int i = 1;i < n; i++){
		scanf("%d",&m);
		if(m>a[k]){//比a中最大数还大,就增加一条轨道 
			k++;
			a[k] = m;
		}
	
		else{ //二分法查找到a中与m最相近的值,然后更新那条轨道上的末尾的数 
			int l = 1;
			int r = k;
			
			while(l<=r){
				int mid = (l+r)/2;
				if(m>=a[mid]){
					l++;
				}
				else{
					r--;
				}
			}
			a[l] = m;
		}
		
	}
		
	printf("%d",k); //打印轨道数k 
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值