2021-01-10

A 二分搜索

Description

给定一个排好序的数字序列,查找某个数字是否存在这个数字序列中

Input

第一行,一个数字n代表有n个数字,0<n≤110000
第二行,n个数字,以空格分隔,已经从小到大排好顺序
接下来若干行,每行一个数字,表示查询的数字。如果数字为0,表示查询结束

Output

对于每个查询,输出一行。如果找到了,输出yes。如果没有找到,输出no。

Sample Input 1

5
2 3 5 7 9
1
2
5
10
0

Sample Output 1

no
yes
yes
no

code

#include <iostream>
using namespace std;
//在已排序(升序)数组a[left...right]中查找元素x,
//如果找到,返回x的下标;否则返回-1
int biSearch(int x, int a[],  int left, int right) {
  if (left > right//(第一个空) )//搜索完毕,未找到该元素
      return -1;
  int m = (left + right)/2//(第二个空)//折半
  if (a[m] > x) //如果中间的数字大于x,在数组左半部分递归查找
     return biSearch(x, a, left, m - 1); //(第三个空) 
  else if (a[m] == x//(第四个空) //如果找到,直接返回位置
     return m;
  else //否则在数组右半部分递归查找
     return biSearch(x, a, m + 1, right);//(第五个空) 
}

int main() {
  int n; 
  cin >> n;
  int a[n];
  for (int i = 0; i < n; i++)
    cin >> a[i];
  int x;
  cin >> x;
  while (x != 0) {
  	if (biSearch(x, a,  0, n-1)>=0)
  		cout << "yes" << endl;
  	else
  		cout << "no" << endl;
  	cin >> x;
  }
}

B 0-1背包

Description

给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。

Input

共有n+1行输入: 第一行为n值和c值,表示n件物品和背包容量c; 接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。

Output

输出装入背包中物品的最大总价值。

Sample Input 1

5 10
2 6
2 3
6 5
5 4
4 6

Sample Output 1

15

code

#include <iostream>
#include <algorithm>
using namespace std;

//利用回溯法求解0-1背包问题
struct Obj {//物品的数据结构
        int weight;
        int value;
};
int cv = 0, cw = 0, bestc = 0;//cv当前总价值,cw当前总重量,bestc当前最优解
int n, c;//n物品总数,c背包容量
Obj* objs;

//限界函数(严格)
float bound(int i) {
        int cleft = c - cw;//背包剩余容量
        int b = cv;//价值上界
        while (i <= n && objs[i].weight < cleft) { //若物品i存在且重量不超过背包剩余容量
                b+= objs[i].value;
                cleft -= objs[i].weight;
                i++;
        }
        if (i <= n) { 
                b += objs[i].value * cleft / objs[i].weight; //用物品的一部分填满背包
        }
        return b;
}

//递归回溯函数
void backtrack(int t) {
        if (t > n//(第一个空)) {//得到问题的一个可能解 
                if (cv > bestc) {
                        bestc = cv;
                }
                return;
        }
        
        //如果满足约束条件,进入左子树
        if (objs[t].weight + cw <= c) {//(第二个空)
                cw += objs[t].weight;
                cv += objs[t].value;
                backtrack(t + 1);
                cv -= objs[t].value;//(第三个空) 
                cw -= objs[t].weight;
        }
        
        //如果满足限界条件,进入右子树
        if (bound(t) > bestc)// (第四个空) 
                backtrack(t + 1);//(第五个空)  
}

//用于排序的比较函数,单位价值高的排在前面
bool cmp(Obj obj1, Obj obj2) {
        if (float(obj1.value) / obj1.weight > float(obj2.value) / obj2.weight)
                return true;
        else
                return false;
}

int main() {
        
        int i;
        cin >> n >> c;
        objs = new Obj[n + 1];
        for (i = 1; i <= n; i++) {
                cin >> objs[i].weight;
                cin >> objs[i].value;
        }
        sort(objs + 1, objs + n + 1, cmp);
        
        backtrack(1);
        cout << bestc;
        return 0;
}

C 购书计划

Description

算法课程虽然结束了。但是小明学习算法的兴趣依然不减,他打算假期再好好地学习一下算法,提高一下自己的编程能力。老师给他推荐了一些不错的算法书单,包括《算法竞赛入门经典》、《挑战程序设计竞赛》、《数据结构与算法分析》等等。他看了看银行卡上的余额,所剩已经不多了。他打算把购买机票后剩下的钱都用来买书。小明也不打算买过于便宜的书。因为书的价格太便宜,意味着内容不够全面,大部分内容他都学过了。看着长长的书单,你能帮小明算算他最多可以买多少本书吗?

Input

第一行4个整数,分别表示小明的银行卡余额r(0 < r < 1000)、机票的价格p(0 < p < 1000)、书的最低价格b(0 < b < 1000)、书单列表长度n(0 < n < 1000)
接下来1行,n个数字,空格分隔,表示n本书的价格

Output

一个整数,表示小明买书的最多数量

Sample Input 1

500 300 30 5
80 70 90 28 118

Sample Output 1

2

Hint

输入样例:

500 300 30 5
30 40 40 30 60

输出样例:

5

输入样例:

500 450 30 5
60 70 80 80 90

输出样例:

0

输入样例:

500 300 70 5
30 50 60 40 35

输出样例:

0

code

#include<iostream>
#include<algorithm>
using namespace std;


int main(){
	int r,p,b,n;
	cin>>r>>p>>b>>n;
	int a[1003];
	for (int i =1;i<=n;i++){
		cin>>a[i];
	}
	int m=r-p;//余额
	int count=0;
	for (int i=1;i<=n;i++){
	    if(a[i]>=b&&m>=a[i]){
		   m-=a[i];
		   count++;
	}
	else
		break;
}
	cout<<count<<endl;
	return 0;
}

D 带书计划

Description

小明买到了他心仪的算法书。他打算带着这些书回家,趁着假期好好学习一下算法。但是由于飞机上有行李重量的限制,大块头的计算机书籍都很重。小明想尽可能用满行李重量的限额,在不超过限额的前提下,带的书越重越好。辛辛苦苦学了一学期算法的你,能帮助小明找到最佳的解决方案吗,告诉他可以带哪些书吗?

Input

第一行3个整数,分别代表飞机重量的限制b(0< b < 1000)、书的数量n(0 < n < 100)。
下面n行,每行一个字符串和整数,空格分隔,代表每本书的名称和重量

Output

按书名的字典排序输出多行,每行代表一本书。如果有多个答案,输出字典序最小的答案。如果一本书都不能带,输出-1

Sample Input 1

20 4 i
ntroduction_algorithm 13
algorithm_training 6
data_struct 15
beauty_of_math 4

Sample Output 1

algorithm_training
introduction_algorithm

Hint

《introduction_algorithm》《algorithm_training》和《data_struct》《beauty_of_math》两种组合都可以获得最大值,取字典序最小的按字典序输出。

code

#include <bits/stdc++.h>
using namespace std;
struct node
{
	string s;
	int num;
	friend bool operator<(node a,node b)
	{
		return a.s<b.s;
	}
}a[1005];
int dp[1005],pre[1005],p[1005];
string dpp[1005];
string ss[105];
int main()
{
	ios::sync_with_stdio(0);
	int n,m;
	cin>>n>>m;
	for(int i = 1; i <= m; i++)
	{
		string s;
		int v;
		cin>>s>>v;
		a[i].s = s,a[i].num = v;
	}
	memset(dp,-1,sizeof(dp));
	dp[0] = 0;
	for(int i = 1; i <= n; i++)
		dpp[i] = "";
	sort(a+1,a+1+m);
	for(int i = 1; i <= m; i++)
		for(int j = n; j >= a[i].num; j--)
		{
			if(dp[j-a[i].num] != -1 && (dp[j] == -1 || dpp[j-a[i].num]+a[i].s < dpp[j]))
			{
				dp[j] = 1;
				pre[j] = i;
				p[j] = j-a[i].num;
				dpp[j] = dpp[j-a[i].num]+a[i].s;
			}
		}
	int mx = -1,pos = -1;
	for(int i = n; i >= 1; i--)
		if(dp[i] == 1){
			mx = i;
			break;
		}
	pos = pre[mx];
	if(mx == -1)
	{
		puts("-1");
		return 0;
	}
	else
	{
		int top = 0;
		while(mx)
		{
			ss[++top] = a[pre[mx]].s;
			mx -= a[pre[mx]].num;
		}
		for(int i = top; i >= 1; i--)
			cout<<ss[i]<<'\n';
	}		
	return 0;
} 

E 学习计划

Description

今年的暑假假期为1月16日至2月27日,一共43天。小明打算利用其中的连续M天(1 ≤ M≤ 1,000)好好学习一下算法。他在中国大学MOOC、Coursera等在线课程网站选择了N门(1 ≤ N ≤ 10,000)不错的网上在线课程,但是这些课程开始的时间S、持续的天数D(1 ≤ Di ≤ M)都是不同的,最早开始时间为0。小明希望完整地选几门课程学习,并且从寒假的第一天到最后一天,每天只上一门课,并且每天有课。每门课程需要完成作业的时间为H,小明做作业的总的时间最多是T (1 ≤ T≤ 1000)。小明根据每门课程介绍的学习内容给每门课程标注了收获值。小明希望在所有课程总的作业时间不超过T的前提下,所有课程总的收获值C最大。请你帮助小明制定他的学习计划吧

Input

第一行空格分隔的三个整数,代表M、N、T
下面N行,每行空格分隔的4个数字,表示每门课程的S、D、C、H

Output

一个整数代表最大的收获值,如果找到满足约束条件的安排计划。如果没有可行计划,输出-1

Sample Input 1

5 6 10
0 2 20 6
2 3 5 6
0 1 2 1
1 1 1 3
1 2 5 4
3 2 10 2

Sample Output 1

17

Hint

选第3、5、6门课程,收获值为17、作业时间为7。如果选择前2门课程,尽管收获值为25,但是作业总时间超过了作业总时间限制10

code

#include <bits/stdc++.h>
using namespace std;
#define ll long long 
struct node
{
	ll s,d,c,h;
	friend bool operator<(node a,node b)
	{
		return a.s==b.s?a.d<b.d:a.s<b.s;
	}
}a[10005];
vector<node> G[1005];
ll dp[1005][1005];
int main()
{
	ll m,n,t;
	cin>>m>>n>>t;
	for(int i = 1; i <= n; i++)
	{
		cin>>a[i].s>>a[i].d>>a[i].c>>a[i].h;
		a[i].s++;
	}
	sort(a+1,a+1+n);
	for(int i = 1; i <= n; i++)
		G[a[i].s].push_back(a[i]);
	memset(dp,-1,sizeof(dp));	
	if(G[1].size() == 0)
	{
		puts("-1");
		return 0;
	}
	dp[1][0] = 0;
	for(int i = 1; i <= m; i++)
	{
		int k = G[i].size();
		for(int j = 0; j < k; j++)
		{
			node b = G[i][j];
			if(b.d+i > m+1)
				continue;
			for(int q = 0; q <= t-b.h; q++)
				if(dp[i][q] != -1)
					dp[b.d+i][q+b.h] = max(dp[b.d+i][q+b.h],dp[i][q]+b.c);
		}
	}
	ll ans = -1;
	for(int i = 0; i <= t; i++)
		ans = max(ans,dp[m+1][i]);	
	printf("%lld\n",ans);				
	return 0;
}
/*
1 1 100
1 1 3 0
3 3 5
1 1 3 0
2 1 4 0
3 1 3 0
*/ 

感谢观看

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值