蓝桥杯刷题记录(待更新)

谨以此文纪念我逝去的青春
我当年不会做的题目合集

一.普通题型


1.P1421 小玉买文具

班主任给小玉一个任务,到文具店里买尽量多的签字笔。已知一只签字笔的价格是 11 元 99 角,而班主任给小玉的钱是 aa 元 bb 角,小玉想知道,她最多能买多少只签字笔呢。

输入只有一行两个整数,分别表示 aa 和 bb。

输出一行一个整数,表示小玉最多能买多少只签字笔。

此题形需要a元b角转换为角的形式进行计算,或者转换为元
#include<bits/stdc++.h>
using namespace std;
int main()
{//纪念我用c++的第一个题目
	int a,b,ans=0;
	cin>>a>>b;
	ans=(a*10+b)/19;
	cout<<ans;
	return 0;
}

2.P1425 小鱼的游泳时间

伦敦奥运会要到了,小鱼在拼命练习游泳准备参加游泳比赛,可怜的小鱼并不知道鱼类是不能参加人类的奥运会的。

这一天,小鱼给自己的游泳时间做了精确的计时(本题中的计时都按24小时制计算),它发现自己从a时b分一直游泳到当天的c时d分,请你帮小鱼计算一下,它这天一共游了多少时间呢?

小鱼游的好辛苦呀,你可不要算错了哦。

一行内输入 4 个整数,分别表示 a, b, c, d。

一行内输出 2 个整数 e 和 f,用空格间隔,依次表示小鱼这天一共游了多少小时多少分钟。其中表示分钟的整数 f 应该小于60。

题型也是将小时转换为分钟,用/和%再转换
#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int a,b,c,d,ans,x,y;
	cin>>a>>b>>c>>d;
	ans=(c-a)*60+(d-b);
	x=ans/60;//转换为小时
	y=ans%60;//转换为分钟
	cout<<x<<" "<<y;
	return 0;
} 
}

3.P1085 不高兴的津津

津津上初中了。妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班。另外每周妈妈还会送她去学习朗诵、舞蹈和钢琴。但是津津如果一天上课超过八个小时就会不高兴,而且上得越久就会越不高兴。假设津津不会因为其它事不高兴,并且她的不高兴不会持续到第二天。请你帮忙检查一下津津下周的日程安排,看看下周她会不会不高兴;如果会的话,哪天最不高兴。

输入包括7行数据,分别表示周一到周日的日程安排。每行包括两个小于10的非负整数,用空格隔开,分别表示津津在学校上课的时间和妈妈安排她上课的时间。

输出包括一个数字。如果不会不高兴则输出0,如果会则输出最不高兴的是周几(用1, 2, 3, 4, 5, 6, 7)分别表示周一,周二,周三,周四,周五,周六,周日)。如果有两天或两天以上不高兴的程度相当,则输出时间最靠前的一天。

题型 数组记录课时,打擂台比出最大的数组,创建变量来记录数组名的操作极其重要
#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
#include<cmath>
using namespace std;
int a[20],b[20],ans[20],maxx=-1;


int main()
{
	for(int i=1;i<=7;i++){
		cin>>a[i]>>b[i];
		ans[i]=a[i]+b[i];	
	}
	for(int i=1;i<=7;i++){
		if(ans[i]>maxx){
		   maxx=ans[i];tot=i;//tot记录下标
		}
	}
	cout<<tot;
	return 0;
} 

4.P1008 三连击

本题为提交答案题,您可以写程序或手算在本机上算出答案后,直接提交答案文本,也可提交答案生成程序。

将 1~9 共 9 个数分成 3 组,分别组成 3 个三位数,且使这 3 个三位数构成 1:2:3 的比例,试求出所有满足条件的 3 个三位数。

输入格式:无输入

输出格式:若干行,每行 3 个数字。按照每行第 1 个数字升序排列。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int a[25];
int v;
int main()
{
	for(int i=100;i<=333;i++){//i为333*3的时候已经可以包括999了 
	    memset(a,0,sizeof(a));
	    v=0;
		a[i%10]=a[i/10%10]=a[i/100] = a[i*2%10]=a[i*2/10%10]=a[i*2/100] = a[i*3%10]=a[i*3/10%10]=a[i*3/100]=1;
	for(int j=1;j<=9;j++){ 
		v+=a[j];
        if(v==9){ 
		  cout<<i<<" "<<i*2<<" "<<i*3;
		  cout<<endl;
		}
	}
}
	return 0;
} 

5.P1618 三连击升级版

将 1~9 共 9 个数分成三组,分别组成三个三位数,且使这三个三位数的比例是 A:B:C,试求出所有满足条件的三个三位数,若无解,输出 No!!!

输入格式:三个数,A,B,C。

输出格式:若干行,每行 33 个数字。按照每行第一个数字升序排列。

题型 此题多种解法,运用数组记录每个数字次数,下标是1~9并且加起来若为9就是每个数字用了一次

题型 此题与上题相似,改个比例,有解的话输出标记很重要

#include<bits/stdc++.h>
using namespace std;
int a[25],b,c,d,v,ans,x,y,z;
int main()
{
	cin>>b>>c>>d;
	for(int i=1;i<=1000/d;i++){
		memset(a,0,sizeof(a));
		v=0;
		x=b*i;
		y=c*i;
		z=d*i;
		a[x%10]=a[x/10%10]=a[x/100] = a[y%10]=a[y/10%10]=a[y/100] = a[z%10]=a[z/10%10]=a[z/100]=1;
		for(int j=1;j<=9;j++){
			v+=a[j];
			if(v==9){
				cout<<x<<" "<<y<<" "<<z;
			    ans++;//非常重要记住的地方
				cout<<endl;
			}
		}
	}
	if(ans==0)cout <<"No!!!";
	return 0;
} 

6.P2141 珠心算测验

珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术。珠心算训练,既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及。

某学校的珠心算老师采用一种快速考察珠心算加法能力的测验方法。他随机生成一个正整数集合,集合中的数各不相同,然后要求学生回答:其中有多少个数,恰好等于集合中另外两个(不同的)数之和?

最近老师出了一些测验题,请你帮忙求出答案。

输入格式:共两行,第一行包含一个整数n,表示测试题中给出的正整数个数。

第二行有n个正整数,每两个正整数之间用一个空格隔开,表示测试题中给出的正整数。

输出格式:一个整数,表示测验题答案。

题型 此题可以背下for(int i=1;i<=n-1;i++){
		for(int j=i+1;j<=n;j++)是枚举i到n的模板,还可以避免重复,重要的是为了避免一个数有两种加起来的方式,需要用数组存储状态。
#include<bits/stdc++.h>
#define shu 10100000
using namespace std;
int n,a[shu],num[shu];
int main()
{
	int ans=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n-1;i++){
		for(int j=i+1;j<=n;j++){
			for(int k=1;k<=n;k++){
				if(a[i]+a[j]==a[k] && !num[k]){
					ans++;
					num[k]=1;
				}
			}
		}
	}
	cout<<ans;
	return 0;
} 

7.P1464 Function

对于一个递归函数w(a,b,c),阿巴阿巴(详情见洛谷题目p1464)

输入格式:
会有若干行。

并以-1,-1,-1结束。

保证输入的数在[-9223372036854775808,9223372036854775807]之间,并且是整数。

第二行有n个正整数,每两个正整数之间用一个空格隔开,表示测试题中给出的正整数。

输出格式:输出若干行,每一行格式:

w(a, b, c) = ans

注意空格。

题型 此题为递归模拟题,但是不能单单模拟,可以用记忆化搜索解题
//首先这是超时的,因为没有用记忆化递归搜索
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int shu = 105;
int a[shu];
ll w(ll a,ll b,ll c){
	if(a<=0 || b<=0 || c<=0){
		return 1;
	}
	else if(a>20 || b>20 || c>20){
		return w(20,20,20);
	}
	else if(a<b && b<c){
		return w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
	}
	else{
		return w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
	}
}
int main()
{
	ll a,b,c;
	while(cin>>a>>b>>c){
		if(a==-1 && b==-1 && c==-1)return 0;
		else printf("w(%I64d,%I64d,%I64d )=%I64d",a,b,c,w(a,b,c));
	}
	
	return 0;
}
//真正的代码
#include<bits/stdc++.h>
using namespace std;
long long rem[22][22][22];
long long w(long long a,long long b,long long c){
	if(a<=0 || b<=0 || c<=0){
		return 1;
	}
	else if(a>20 || b>20 || c>20){
		return w(20,20,20);
	}
	else if(rem[a][b][c]){
		return rem[a][b][c];
	}
	else if(a<b && b<c){
		return rem[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
	}
	else{
		return rem[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
	}
}
int main()
{
	long long a,b,c;
	while(1){
		cin>>a>>b>>c;
		if(a==-1 && b==-1 && c==-1){
			return 0;
		}
		cout<<"w(" << a <<", "<<b<<", "<<c<<") = "<<w(a,b,c);
		cout<<endl;
	}
	return 0;
}


8.P1014 [NOIP1999 普及组] Cantor 表

题目描述
现代数学的著名证明之一是 Georg Cantor 证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的:
阿巴阿巴…(详情见洛谷题目p1014)

我们以 Z 字形给上表的每一项编号。第一项是 1/1,然后是 1/2,2/1,3/1,2/2,…

输入格式
整数N(1≤N≤10的7次方)。

输出格式
表中的第 N 项。

题型 我反正是永远找不出规律的规律题
1.奇数斜行往下走,偶数斜行往上走
2.求n在第几斜行的方法是 while(n-a>0){n-=a;a++}
3./号两边加起来等于下一行,所以偶数斜行的表示为cout<<n/a+1-n,奇数行表示为.....
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;

int main()
{
	int n,a=0;
	cin>>n;
	while(n-a>0){//预判下一次<0就可以不用写a-1了 
		n-=a;
		a++;//行 
	}
	if(a%2==0){
		cout<<n<<"/"<<a+1-n;
	}
	else cout<<a+1-n<<"/"<<n;
	return 0;
}

二.普通字符题型


1.P1055 ISBN 号码

每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如x-xxx-xxxxx-x,其中符号-就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如00代表英语;第一个分隔符-之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。

识别码的计算方法如下:

首位数字乘以11加上次位数字乘以2……以此类推,用所得的结果mod11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码44是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,…,9再求和,即0×1+6×2+……+2×9=1580×1+6×2+……+2×9=158,然后取158mod11的结果4作为识别码。

你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出Right;如果错误,则输出你认为是正确的ISBN号码。

题型是非常简单的字符串的模拟,这类题目主要记住字符转数字需要-‘0’
#include<bits/stdc++.h>
#define shu 10100000
using namespace std;
string s;
int main()
{
	cin>>s;
		int sum=(s[0]-'0')*1 + (s[2]-'0')*2 + (s[3]-'0')*3 + (s[4]-'0')*4 + (s[6]-'0')*5 + (s[7]-'0')*6 + (s[8]-'0')*7 + (s[9]-'0')*8 + (s[10]-'0')*9;
		if(s[12]=='X'){
			if(sum%11==10){
				cout<<"Right";
				return 0;
			}
		}
		if(sum%11==s[12]-'0'){
			cout<<"Right";
			return 0;
		}
		else {
			for(int i=0;i<12;i++){
				cout<<s[i];
			}
			if(sum%11==10){
				cout<<'X';
			}
			else
			cout<<sum%11;
		}
	return 0;
}


2.P1200 你的飞碟在这儿Your Ride Is Here

众所周知,在每一个彗星后都有一只UFO。这些UFO时常来收集地球上的忠诚支持者。不幸的是,他们的飞碟每次出行都只能带上一组支持者。因此,他们要用一种聪明的方案让这些小组提前知道谁会被彗星带走。他们为每个彗星起了一个名字,通过这些名字来决定这个小组是不是被带走的那个特定的小组(你认为是谁给这些彗星取的名字呢?)。关于如何搭配的细节会在下面告诉你;你的任务是写一个程序,通过小组名和彗星名来决定这个小组是否能被那颗彗星后面的UFO带走。

小组名和彗星名都以下列方式转换成一个数字:最终的数字就是名字中所有字母的积,其中A是1,Z是26。例如,USACO小组就是21×19×1×3×15=17955。如果小组的数字mod47等于彗星的数字mod47,你就得告诉这个小组需要准备好被带走!

写出一个程序,读入彗星名和小组名并算出用上面的方案能否将两个名字搭配起来,如果能搭配,就输出“GO”,否则输出“STAY”。小组名和彗星名均是没有空格或标点的一串大写字母(不超过66个字母)。

题型是非常简单的字符串的模拟
主要记住:
小写字母转26进制:char a=a-'a'+1; 
大写字母转26进制:char a=a-'A'+1; 
小写字母转大写字母:char a=a+'A'-'a'; 
大写字母转小写字母:char a=a+'a'-'A'; 
字符转数字:char a=a-'0';
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
//小写字母转26进制:char a=a-'a'+1; 
//大写字母转26进制:char a=a-'A'+1; 
char a[1001000];
char s[1001000];
int main()
{
	int sum1=1,sum2=1;
	cin>>a;
	cin>>s;
	for(int i=0;i<=strlen(a)-1;i++){
			sum1*=a[i]-'A'+1;
	}
	sum1=sum1%47;
	for(int i=0;i<=strlen(s)-1;i++){
			sum2*=s[i]-'A'+1;
	}
	sum2=sum2%47;
	if(sum1==sum2){
		cout<<"GO";
		return 0;
	}
	else {
		cout<<"STAY";
	}
	return 0;
}

3.P1308 统计单词数

一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。

现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例1 ),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2 )。

输入格式:
共2行。

第1行为一个字符串,其中只含字母,表示给定单词;

第2行为一个字符串,其中只可能包含字母和空格,表示给定的文章。

输出格式:
一行,如果在文章中找到给定单词则输出两个整数,两个整数之间用一个空格隔开,分别是单词在文章中出现的次数和第一次出现的位置(即在文章中第一次出现时,单词首字母在文章中的位置,位置从0 开始);如果单词在文章中没有出现,则直接输出一个整数−1。

题型又又又是简单的模拟字符串,这题添加了很多条件,利用stl函数可以很方便。
1.这题char类型字符串用gets()读入很好
  因为string和char类型cin读入的话遇到空格则停止输入了
  所以为了让char类型输入带空格必须用gets()读入一行数据以回车结束 
2.而为了让string输入带空格,需要用getline(cin,string)读取一行数据以回车结束,
3.s.find(a); 字符串a在字符串s中第一次出现的位置  未找到时会出现-1;
 
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
string a,b;
int main()
{
	int ans=0;
	getline(cin,a);
	getline(cin,b);
	for(int i=0;i<=a.length()-1;i++){//转换大小写 
		if(a[i]>='A'&&a[i]<='Z'){
			a[i]+='a'-'A';
		}
	}
	for(int i=0;i<=b.length()-1;i++){
		if(b[i]>='A'&&b[i]<='Z'){
			b[i]+='a'-'A';
		}
	}
	a=' '+a+' ';//非常重要,前后加上空格才能绝对判定是一个单词而不是某个单词的部分 
	b=' '+b+' ';//非常重要,文章前后加空格才能知道第一个和最后一个是不是匹配a
	int firsttime;//记录第一次出现的位置
	int nexttime;//记录有多少次
	if(b.find(a)==-1){
		cout<<"-1";
		return 0;
	} 
	else {
		firsttime=b.find(a);
		nexttime=b.find(a);
	}
	while(nexttime!=-1){
		ans++;
		nexttime=b.find(a,nexttime+1);//记录完就开始查下一个 
	}
	cout<<ans<<" "<<firsttime;
	return 0;
}

4.P1553 数字反转升级版

题目描述
给定一个数,请将该数各个位上数字反转得到一个新数。

这次与NOIp2011普及组第一题不同的是:这个数可以是小数,分数,百分数,整数。

整数反转是将所有数位对调。

小数反转是把整数部分的数反转,再将小数部分的数反转,不交换整数部分与小数部分。

分数反转是把分母的数反转,再把分子的数反转,不交换分子与分母。

百分数的分子一定是整数,百分数只改变数字部分。

输入格式
一个数 s

输出格式
一个数,即 s 的反转数

数据保证:

对于整数翻转而言,整数原数和整数新数满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数和原来的数字的最高位数字不应为零。

对于小数翻转而言,其小数点前面部分同上,小数点后面部分的形式,保证满足小数的常见形式,也就是末尾没有多余的 00(小数部分除了 00 没有别的数,那么只保留 11 个 00。若反转之后末尾数字出现 00,请省略多余的 00)

对于分数翻转而言,分数不约分,分子和分母都不是小数。输入的分母不为0。与整数翻转相关规定见上。

对于百分数翻转而言,见与整数翻转相关内容。

数据不存在负数。

题型是一道比较 简单(划掉)的模拟题
去零的操作基本上都是定义变量记录多少个0
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
string s;
int p;
//如何去0?用变量记录
//如果s=0,也要输出0
//小数点后的零:数字前的去掉,数字后的留下
//分数后的零 :数字后的零去掉 
int main()
{
	cin>>s;
	int leng=s.length();
	int p=leng;
	for(int i=1;i<leng;i++){
		if(s[i]=='.'||s[i]=='/'||s[i]=='%'){
			p=i;
		}
	}
	int lin=1;
	for(int i=p-1;i>=0;i--){
		if(s[i]=='0' && lin==1 && i>0)//i>0很重要,s=0也要输出0 
		continue;
		lin=0;//把不要的后缀0去掉 ,前面的和中间的要留下来,这步去除后面且连续的0,所以lin要等于0防止中间的0被消除 
		cout<<s[i];
	}//这里得到了整数的25分 
	if(p!=leng){
		cout<<s[p];
  }//完成%的25分 
  if(s[p]=='/'){
		lin=1;
	    for(int i=leng-1;i>=p+1;i--){
		if(s[i]=='0' && lin==1 && i>p+1)
		continue;
		lin=0;
		cout<<s[i];
      } 	
    }//完成/的25分 
    if(s[p]=='.'){
    	int temp=p+1;
    	while(s[temp]=='0' && temp<leng-1)temp++;//前面多少个0 
    	 for(int i=leng-1;i>=temp;i--){
    	 	cout<<s[i];
    	 }
    } //完成.的25分 
	return 0;
}

5.P1598 垂直柱状图

题目描述
写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过100个字符),然后用柱状图输出每个字符在输入文件中出现的次数。严格地按照输出样例来安排你的输出格式。

输入格式
四行字符,由大写字母组成,每行不超过100个字符

THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG.
THIS IS AN EXAMPLE TO TEST FOR YOUR
HISTOGRAM PROGRAM.
HELLO!

输出格式
由若干行组成,前几行由空格和星号组成,最后一行则是由空格和字母组成的。在任何一行末尾不要打印不需要的多余空格。不要打印任何空行。

                            *
                            *
        *                   *
        *                   *     *   *
        *                   *     *   *
*       *     *             *     *   *
*       *     * *     * *   *     * * *
*       *   * * *     * *   * *   * * * *
*     * * * * * *     * * * * *   * * * *     * *
* * * * * * * * * * * * * * * * * * * * * * * * * *
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
1.读入
2.装桶(统计)
3.求最大值用来看输出多少行
4.画图
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
char s[110];
int cnt[30];
int main()
{
	int maxx=-1;
	gets(s);
	for(int i=0;i<strlen(s);i++){//字母数字转换变成下标记录 
		cnt[s[i]-'A']++;
	}
	gets(s);
	for(int i=0;i<strlen(s);i++){
		cnt[s[i]-'A']++;
	}
	gets(s);
	for(int i=0;i<strlen(s);i++){
		cnt[s[i]-'A']++;
	}
	gets(s);
	for(int i=0;i<strlen(s);i++){
		cnt[s[i]-'A']++;
	}
	for(int i=0;i<26;i++){
		if(maxx<cnt[i])maxx=cnt[i];
	}
	for(int i=maxx;i>=1;i--){
		for(int j=0;j<26;j++){
			if(cnt[j]>=i)
			cout<<"*"<<" ";
			else 
			{
				cout<<"  ";
			}
		}
		cout<<endl;
	}
	for(char i='A';i<='Z';i++){
		cout<<i<<" ";
	}
	return 0;
}

6.P1071 [NOIP2009 提高组] 潜伏者

题目描述
见洛谷p1071

输入格式
见洛谷p1071

输出格式
见洛谷p1071

靠数组巴拉巴拉,有点难
#include<bits/stdc++.h>
using namespace std;
string x,y;
char a[100],b[100];
int len,cnt;
int main()
{
	memset(a,'?',sizeof(a));//先初始化空 
	memset(b,'?',sizeof(b));//初始化空 
	cin>>x>>y;
	for(int i=0;i<x.length();i++){
		if(a[x[i]]=='?' && b[y[i]]=='?'){
			a[x[i]]=y[i];
			b[y[i]]=x[i];
			cnt++;
		}
		else if(a[x[i]]!=y[i]){
			cout<<"Failed";
			return 0;
		}//可以不空但一定得相等,否则就是错的 
	}
	if(cnt<26){
		cout<<"Failed";
		return 0;
	}
	string t;
	cin>>t;
	for(int i=0;i<t.length();i++){
		cout<<a[t[i]];
	}
	return 0;
} 

7.P1012 [NOIP1998 提高组] 拼数

题目描述
见洛谷p1012

输入格式
见洛谷p1012

输出格式
见洛谷p1012

string a【】,b【】开数组 a+b的意思就是字母连起来
#include<bits/stdc++.h>
using namespace std;
const int shu = 1e8;
string s[25];
bool cmp(string a,string b){
	return a+b>b+a;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>s[i];
	}
	sort(s+1,s+1+n,cmp);
	for(int i=1;i<=n;i++){
		cout<<s[i];
	}
	return 0;
} 

三.模拟算法题型


1.P1003 [NOIP2011 提高组] 铺地毯

题目描述
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n 张地毯,编号从 1 到 n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。

地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。

输入格式
输入共 n+2 行。

第一行,一个整数 n,表示总共有 n 张地毯。

接下来的 n 行中,第 i+1行表示编号 i 的地毯的信息,包含四个整数 a ,b ,g ,k每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标 (a,b) 以及地毯在 x 轴和 y 轴方向的长度。

第 n + 2 行包含两个整数 x 和 y,表示所求的地面的点的坐标 (x,y)。

输出格式
输出共 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出 -1。

模拟解决此题,可以从最后一个输入的数据开始排查,
如果说你找到了这个点上面有地毯,
那么就直接输出这个值,
如果没找到就按照题干的意思输出-1。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
const int shu = 1000500;
int n,a[shu],b[shu],x[shu],y[shu],aa,bb;

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i]>>x[i]>>y[i];
	}
	cin>>aa>>bb;
	for(int i=n;i>0;i--){
		if(a[i]<=aa && b[i]<=bb && a[i]+x[i]>=aa && b[i]+y[i]>=bb){
			cout<<i<<endl;
			return 0;
		}
	}
	cout<<"-1";
	return 0;
} 

2.P1067 [NOIP2009 普及组] 多项式输出

题目描述
详情见洛谷p1067

输入格式
输入共有 2 行

第一行1个整数,n,表示一元多项式的次数。

第二行有n+1个整数,其中第i个整数表示第n-i+1次项的系数,每两个整数之间用空格隔开。

输出格式
输出共 1 行,按题目所述格式输出多项式。

模拟解决此题,此题坑太多了
1.+和-的判断要分第一项 最后一项 中间的项
2.输出的n要--,因为a[i]=0跳过的数也要记得n--
3最后的常数的符号判断
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
const int shu = 1000500;
int a[shu],n;

int main()
{
	cin>>n;
	int nn=n;
	for(int i=1;i<=n+1;i++){
		cin>>a[i];
		if(a[i]==0){
			nn--;
			continue;
		}
		if(i==n+1){
			if(a[i]>0){
				cout<<"+"<<a[i];
				return 0;
			}
			else {
				cout<<a[i];
				return 0;
			}
		}
		if(a[i]>=0 &&i!=1 ){
			cout<<"+";
		}
		if(a[i]==-1){
			cout<<"-";
		}
		else{
			if(a[i]!=1){
				cout<<a[i];
			}
		}
		if(nn==1){
			cout<<"x";
			nn--;
		}
		else{
		cout<<"x^"<<nn;
		nn--;
		}
	}
	return 0;
} 

3.P1540 [NOIP2010 提高组] 机器翻译

题目描述
这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。

假设内存中有 M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过 M−1,软件会将新单词存入一个未使用的内存单元;若内存中已存入 M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。

假设一篇英语文章的长度为 N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

输入格式
共 2 行。每行中两个数之间用一个空格隔开。

第一行为两个正整数 M,N代表内存容量和文章的长度。

第二行为 N 个非负整数,按照文章的顺序,每个数(大小不超过 1000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。

输出格式
一个整数,为软件需要查词典的次数。

模拟解决此题,好像用了桶?
a[i]记录输入
b[ a[i] ]记录是不是已经存入,存过的都赋值1,
        没赋值也就是为0的也就是没存过需要r++的 
q[++r] 每次记录右边的数,为了判断有没有存入和为了r++ 
l 记录左边,如果右边-左边大于m,l就要++,
   当l++的时候,b[q[l]]=0,让被挤出去的变成没记录的 
r 记录右边 因为存过的会跳过,所以也就是最后答案 
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
const int shu = 10500;
int n,m,b[shu],q[shu],a[shu],l,r;

int main()
{
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	} 
	l=1,r=0;
	for(int i=1;i<=n;i++){
		if(b[a[i]]==0){
			q[++r]=a[i];
			b[a[i]]=1;
		}
		if(r-l>=m){
			b[q[l]]=0;
			l++;
		}
	}
	cout<<r;
	return 0;
} 

4.P1056 [NOIP2008 普及组] 排座椅

题目描述
上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的 D 对同学上课时会交头接耳。

同学们在教室中坐成了 M 行 N 列,坐在第 i 行第 j 列的同学的位置是 (i,j),为了方便同学们进出,在教室中设置了 K 条横向的通道,L 条纵向的通道。

于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了 2 个会交头接耳的同学,那么他们就不会交头接耳了。

请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生的对数最少。

输入格式
见洛谷p1056

输出格式
见洛谷p1056

模拟解决此题
1.x相同,y不同,选小的,竖着切
2.y相同,x不同,选小的,横着切
3.数组记录下标,选人多的,按坐标输出而不是隔开人数顺序输出
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
const int shu = 10500;
//教室中坐成了 M 行 N 列
//教室中设置了 K 条横向的通道,L 条纵向的通道
// D 对同学上课时会交头接耳
int m,n,k,l,d,a[shu],b[shu],x,xx,y,yy;

int main()
{
	cin>>m>>n>>k>>l>>d;
	for(int i=1;i<=d;i++){
		cin>>x>>xx>>y>>yy;
		if(x==y){
			a[min(xx,yy)]++;//竖着切 
		}
		else if(xx=yy){
			b[min(x,y)]++;//横着切 
		}
	}
	while(k--){
		int maxx=0,p;
		for(int i=1;i<=m;i++){
		if(maxx<b[i]){
			maxx=b[i];
			p=i;
		}
	}
	b[p]=-1;
	}
	while(l--){
		int maxx=0,p;
		for(int i=1;i<=n;i++){
		if(maxx<a[i]){
			maxx=a[i];
			p=i;
		}
	}
	a[p]=-1;
	}
	for(int i=1;i<=m;i++){
		if(b[i]==-1){
			cout<<i<<" ";
		}
	}
	cout<<endl;
	for(int i=1;i<=n;i++){
		if(a[i]==-1){
			cout<<i<<" ";
		}
	}
	return 0;
} 

四.深搜广搜题型


1.P1683 入门

题目描述:见洛谷p1683

纪念我第一个独自ac的深搜题
#include<bits/stdc++.h>
using namespace std;
int w,h,vis[205][205],ans;
char a[205][205];
int aa[]={1,0,0,-1};
int bb[]={0,-1,1,0};

void dfs(int x,int y){
	for(int i=0;i<4;i++){
		int dx=aa[i]+x;
		int dy=bb[i]+y;
		if(vis[dx][dy]==0&&a[dx][dy]=='.'&&dx>=1&&dx<=h&&dy>=1&&dy<=w){
			vis[dx][dy]=1;
			ans++;
			dfs(dx,dy);
		}
	}
}

int main()
{
	cin>>w>>h;
	for(int i=1;i<=h;i++){
		for(int j=1;j<=w;j++){
			cin>>a[i][j];
		}
	}
	ans++;
	for(int i=1;i<=h;i++){
		for(int j=1;j<=w;j++){
			if(a[i][j]=='@'){
				vis[i][j]=1;
				dfs(i,j);
			}
		}
	}
	cout<<ans;
	return 0; 
}

2.P1747 好奇怪的游戏

题目描述:见洛谷p1747

纪念我第二个独自ac的深搜题
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
int x1,y1,x2,y2;
int vis[400][400];
int aa[]={2,2,1,1,-2,-2,-1,-1,2,2,-2,-2};
int bb[]={-1,1,-2,2,-1,1,-2,2,-2,2,-2,2};
struct horse{
	int x,y,s; 
};
queue<horse>Q;
int bfs(int x,int y){
	Q.push((horse){x,y,0});
	while(!Q.empty()){
		for(int i=0;i<12;i++){
		int dx=aa[i]+Q.front().x;
		int dy=bb[i]+Q.front().y;
		if(dx>=1&&dy>=1&&!vis[dx][dy]){
			if(dx==1&&dy==1){
				return Q.front().s+1;
			}
			vis[dx][dy]=1;
			Q.push((horse){dx,dy,Q.front().s+1});
		}
	}
	Q.pop();
	}
}
int main()
{
	cin>>x1>>y1>>x2>>y2;
	cout<<bfs(x1,y1)<<endl;
	memset(vis,0,sizeof(vis));
	while(!Q.empty()) Q.pop();
	cout<<bfs(x2,y2);
	return 0;
}


3.P1451 求细胞数量

题目描述:见洛谷p1451

深搜模板染色
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int n,m,color;
char a[110][110];
int vis[110][110];
int aa[]={-1,1,0,0};
int bb[]={0,0,-1,1};
int dfs(int x,int y){
	for(int i=0;i<4;i++){
		int dx=aa[i]+x;
		int dy=bb[i]+y;
		if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!vis[dx][dy]&&a[dx][dy]!='0'){
			vis[dx][dy]=1;
			dfs(dx,dy);
		}
	}
} 

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]!='0'&&!vis[i][j]){
				vis[i][j]=1;
				color++;
				dfs(i,j);
			}
		}
	}
	cout<<color;
	return 0;
}

4.P1434 [SHOI2002]滑雪

题目描述:见洛谷p1434

深搜+记忆化搜索,很有意思的一道题目
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int r,c,a[200][200],ans,dp[200][200];
int aa[]={-1,1,0,0};
int bb[]={0,0,-1,1}; 
int dfs(int x,int y){
	int maxn=1;
	if(dp[x][y]!=0)return dp[x][y];
	for(int i=0;i<4;i++){
		int dx=aa[i]+x;
		int dy=bb[i]+y;
		if(dx>=1&&dx<=r&&dy>=1&&dy<=c&&a[dx][dy]<a[x][y]){
			maxn=max(maxn,dfs(dx,dy)+1);
		}
	}
	return dp[x][y]=maxn;
}

int main()
{
	cin>>r>>c;
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			ans=max(ans,dfs(i,j));
		}
	}
	cout<<ans;
	return 0;
}

5.P1433 吃奶酪

题目描述:见洛谷p1433

本着要ac人生中第一道绿题的心态,无奈要用状压dp,现在的代码只能拿90分
#include<bits/stdc++.h>
using namespace std;
int n,v[20];
double ans=100000;
double a[20],b[20];
double dis(int x,int y){
	return sqrt( (a[x]-a[y])*(a[x]-a[y]) + (b[x]-b[y])*(b[x]-b[y]) );
}
void dfs(int p,int cur,double s){
	if(s>ans)
	     return ;
	     if(p==n){
	     	ans=min(ans,s);
	     	return ;
	     }
	     for(int i=1;i<=n;i++){
	     	if(!v[i]){
	     		v[i]=1;
	     		dfs(p+1,i,s+dis(cur,i));
	     		v[i]=0;
	     	}
	     }
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i]>>b[i];
		dfs(0,0,0);
		printf("%.2lf",ans);
	return 0;
}

五.广搜题型


1.P2298 Mzc和男家丁的游戏

题目描述:见洛谷p2298

广搜模板题
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int n,m;
char a[2005][2005];
int vis[2005][2005];
struct nd{
	int x,y,s;
};
int aa[]={1,0,0,-1};
int bb[]={0,-1,1,0};
queue<nd>Q;
int bfs(int x,int y){
	Q.push((nd){x,y,0});
	while(!Q.empty()){
		for(int i=0;i<4;i++){
			int dx=aa[i]+Q.front().x;
			int dy=bb[i]+Q.front().y;
			if(a[dx][dy]=='d'){
				cout<< Q.front().s+1;
				return 0;
			}
			if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!vis[dx][dy]&&a[dx][dy]=='.'){
				vis[dx][dy]=1;
				Q.push((nd){dx,dy,Q.front().s+1});
			}
		}
		Q.pop();
	}
	cout<<"No Way!";
	return 0;
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]=='m'){
				bfs(i,j);
			}
		}
	}
	return 0;
}

2.P1746 离开中山路

题目描述:见洛谷p1746

广搜模板题,顺便纪念这辈子第一次不编译直接交直接ac的广搜题
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int n,x1,y1,x2,y2,vis[1005][1005];
char a[1005][1005];
int aa[]={-1,0,0,1};
int bb[]={0,-1,1,0};
struct jl{
	int x,y,s;
};
queue<jl>Q;
int bfs(int x,int y){
	Q.push((jl){x,y,0});
	while(!Q.empty()){
		for(int i=0;i<4;i++){
			int dx=aa[i]+Q.front().x;
			int dy=bb[i]+Q.front().y;
			if(dx==x2&&dy==y2){
				cout<<Q.front().s+1;
				return 0;
			}
			if(dx>=1&&dx<=n&&dy>=1&&dy<=n&&!vis[dx][dy]&&a[dx][dy]!='1'){
				Q.push((jl){dx,dy,Q.front().s+1});
				vis[dx][dy]=1;
			}
		}
		Q.pop();
	}
}

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j];
		}
	}
	cin>>x1>>y1>>x2>>y2;
	vis[x1][y1]=1;
	bfs(x1,y1);
	return 0;
}

六.排序


1.P1177快速排序模板

利用快速排序算法将读入的 NN 个数从小到大排序后输出。

输入格式
输入n

输出格式
用快速排序将n从大到小排序

模板
#include<bits/stdc++.h>
using namespace std;
int a[1000005];
void qsort(int l,int r){
	int x=l,y=r,mid=a[(x+y)/2];
	while(x<=y){
		while(a[x]<mid)x++;
		while(a[y]>mid)y--;
		if(x<=y){
			int q=a[x];
			a[x]=a[y];
			a[y]=q;
			x++;
			y--;
		}
	}
	if(y>l)qsort(l,y);
	if(x<r)qsort(x,r);
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	qsort(1,n);
	for(int i=1;i<=n;i++){
		cout<<a[i]<<" "; 
	}
	return 0;
} 

2.P1781 宇宙总统

题目描述
地球历公元 6036 年,全宇宙准备竞选一个最贤能的人当总统,共有 n 个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统。

输入格式
第一行为一个整数 n,代表竞选总统的人数。

接下来有 n 行,分别为第一个候选人到第 n 个候选人的票数。

输出格式
共两行,第一行是一个整数 m,为当上总统的人的号数。

第二行是当上总统的人的选票。

由于是string类型,先比长度然后比字典序就完事了
#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n,p;
	string x,ans;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x;
		if(x.length()>ans.length()||x.length()==ans.length() && x>ans){
			ans=x;
			p=i;
		}
	}
	cout<<p<<endl<<ans;
	return 0;
} 

七.二分查找与二分答案


1.P1824 进击的奶牛

题目描述见洛谷p1824

二分答案模板,此题难点在于如何判断真假,建立变量一个个比较是很好的方法
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long a[1000000];
long long n,c;
bool f(int b){
	long long aa=0,last=-100000000;
	for(int i=1;i<=n;i++){
		if(a[i]-last>=b){
			aa++;
			last=a[i];
		}
	}
	if(aa>=c)return true;
	else return false;
}

int main()
{
	cin>>n>>c;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	long long l=1,r=1000000000,ans=0;
	while(l<=r){//找满足条件的最大 
		int mid=l+(r-l)/2;
		if(f(mid)){
			ans=mid;
			l=mid+1;
		}
		else r=mid-1;
	}
	cout<<ans;
	return 0;
} 

八.动态规划的背包


1.P1164 小A点菜

题目描述见洛谷p1164

01背包的求方案数
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,c[10050],dp[10050];


int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>c[i];
	}
	dp[0]=1;
	for(int i=1;i<=n;i++){
		for(int j=m;j>=c[i];j--){
			dp[j]=dp[j]+dp[j-c[i]];
		}
	}
	cout<<dp[m];
	return 0;
} 

2.P1510 精卫填海

题目描述见洛谷p1510

01背包的变化
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<iostream>
using namespace std;
int v,n,c; //v体力的判断 n数量选项 c体力容量 
int a[10010],b[10010],dp[100100];//a木材体积是价值 b体力是重量 
int main()
{
	cin>>v>>n>>c;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
	} 
	for(int i=1;i<=n;i++){
		for(int j=c;j>=b[i];j--){
			dp[j]=max(dp[j],dp[j-b[i]]+a[i]);//搬运木材重量 
		}
	} 
	for(int i=1;i<=c;i++){
		if(dp[i]>=v){
			cout<< c-i;
			return 0;
		}
	}
	cout<<"Impossible";
	return 0;
}

3.P1466 [USACO2.2]集合 Subset Sums

题目描述见洛谷p1466

01背包求方案数的变化
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
long long n,dp[800];


int main()
{
	dp[0]=1;
	cin>>n;
	int t=n*(n+1)/2;
	if(t%2==1){
		cout<<"0";
		return 0;
	}
	for(int i=1;i<=n;i++){
		for(int j=t/2;j>=i;j--){
			dp[j]+=dp[j-i];
		}
	}
	cout<<dp[t/2]/2;
	return 0;
} 

4.P1679 神奇的四次方数

题目描述见洛谷p1679

完全背包问题
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
int c[100],v[100],dp[100100];

int main()
{
	cin>>n;
	memset(dp,63,sizeof(dp));
	dp[0]=0;
	int m; 
	for(int i=1;i*i*i*i<=n;i++){
		c[i]=i*i*i*i;
		m=i;
	} 
	for(int i=1;i<=m;i++){
		for(int j=c[i];j<=n;j++){
			dp[j]=min(dp[j],dp[j-c[i]]+1);
		}
	}
	cout<<dp[n];
	return 0;
} 

5.P1757 通天之分组背包

题目描述见洛谷p1757

分组背包问题模板
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
int m,n,c[1010],v[1010],b[1010],dp[1010],g[205][205],s,num;


int main()
{
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>c[i]>>v[i]>>s;
		num=max(s,num);//有几个组?这是个未知的问题,s有多大就有几个组 
		b[s]++;//分组背包用于看每组有几个物品? 
		g[s][b[s]]=i;//第几组中第几个物品的编号,为什么要求编号?因为后面要比较选出每个组价值最高的物品 
	}
	for(int i=1;i<=num;i++){//分组背包模板 
		for(int j=m;j>=0;j--){
			for(int k=1;k<=b[i];k++){//枚举小组中所有成员 
				if(j>=c[g[i][k]]){
					dp[j]=max(dp[j],dp[j-c[g[i][k]]]+v[g[i][k]]);
				} 
			} 
		}
	} 
	cout<<dp[m];
	return 0;
} 

九.贪心


1.P1478 陶陶摘苹果(升级版)

题目描述
又是一年秋季时,陶陶家的苹果树结了 n 个果子。陶陶又跑去摘苹果,这次他有一个 a 公分的椅子。当他手够不着时,他会站到椅子上再试试。

现在已知 n 个苹果到达地上的高度 xi ,椅子的高度 a,陶陶手伸直的最大长度 b,陶陶所剩的力气 s,陶陶摘一个苹果需要的力气 yi,求陶陶最多能摘到多少个苹果。

输入格式
第 1 行:两个数 苹果数 n,力气 s。

第 2 行:两个数 椅子的高度 a,陶陶手伸直的最大长度 b。

第 3 行~第 3+n−1 行:每行两个数 苹果高度 xi ,摘这个苹果需要的力气 yi。

输出格式
只有一个整数,表示陶陶最多能摘到的苹果数。

非常简单的贪心问题
贪心一般要做的:1.确定可以贪心。
              2.建立struct类型组。
              3.自定义函数cmp决定顺序,记得sort。
              4.搞清楚排序后干什么。
#include<bits/stdc++.h>
using namespace std;
int n,s,a,b,xx,yy;
struct apple{
	int xi,yi;
}aa[50050];
bool cmp(apple x,apple y){
	return x.yi<y.yi; //苹果高度,摘这个苹果需要的力气
}
int main()
{
	int ans=0,top=0;
	cin>>n>>s;//苹果数n,力气s。
	cin>>a>>b;// 椅子的高度a,手伸直的最大长度b。
	for(int i=1;i<=n;i++){
		cin>>aa[i].xi>>aa[i].yi;
		}
	sort(aa+1,aa+1+n,cmp);
	for(int i=1;i<=n;i++){
		if(a+b<aa[i].xi)continue;
		if(s>=aa[i].yi){
			ans++;
			s-=aa[i].yi;
		}
	}
	cout<<ans;
	return 0;
}

2.P1181 数列分段 Section I

见洛谷p1181

对于当前元素只有两种选择 并到其他段上和单独一段。
当前元素能在一起的就并上,找不到就自己就自己一段。
#include<bits/stdc++.h>
using namespace std;
int a[1005000];

int main()
{
	int n,m;
	cin>>n>>m;
	int ans=n+1;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		if(a[i]+a[i-1]<=m){
			a[i]+=a[i-1];
			ans--;
		}
	}
	cout<<ans;
	return 0;
} 

3.P1094 [NOIP2007 普及组] 纪念品分组

见洛谷p1094

贪心的难处在于找如何贪心与证明能不能贪心,
此题先sort排序,把最大的和最小的比较消除才能获得最少组,证明这个思路,就可以贪心了
#include<bits/stdc++.h>
using namespace std;
int a[100005];
int main()
{
	int n,w;
	cin>>n>>w;
	int s=0,ans=0,ss=0;
	for(int i=1;i<=w;i++){
		cin>>a[i];
	}
	 sort(a+1,a+1+w);
	 int l=1,r=w;
	 while(l<=r){
	 	if(a[l]+a[r]<=n){
	 		ans++;
	 		l++;
	 		r--;
	 	}
	 	else {
	 		ans++;
	 		r--;
	 	}
	 }
	 cout<<ans;
	return 0;
} 

4.P1208 [USACO1.3]混合牛奶 Mixing Milk

见洛谷p1208

找单价最小排序即可
#include<bits/stdc++.h>
using namespace std;
struct milk{
	int aa,bb;
}a[1000050];
bool cmp(milk x,milk y){
	return x.aa < y.aa;
}
int main()
{
	int n,m,ans=0;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>a[i].aa>>a[i].bb;
	}
	sort(a+1,a+1+m,cmp);
	for(int i=1;i<=m;i++){
		if(n>=a[i].bb){
			ans+=a[i].aa*a[i].bb;
			n-=a[i].bb;
		}
		else {
			ans+=n*a[i].aa;
			break;
		}
	}
	cout<<ans;
	return 0;
} 

5.P1223 排队接水

见洛谷p1223

时间最小的放前面能使平均时间最小
总时间是sum+=i*a[n-i].x;  //n个a[1] n-1个a[2] .....
#include<bits/stdc++.h>
using namespace std;
struct water{
	int x,y;
}a[1050];

bool cmp(water aa,water bb){
	if(aa.x!=bb.x)
	return aa.x<bb.x;
	return aa.y<bb.y;
}

int main()
{
	int n;
	double sum=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].x;
		a[i].y=i;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		cout<<a[i].y<<" ";
	}
	cout<<endl;
	for(int i=1;i<=n;i++){
		sum+=i*a[n-i].x;//n个a[1] n-1个a[2] ..... 
	}
	printf("%.2lf",1.0*sum/n);
	return 0;
}

6.P1803 凌乱的yyy / 线段覆盖

见洛谷p1803

如果两个比赛时间冲突、包含、相交,选先结束的;
最先开始选的比赛,也选最先结束的,贪心
#include<bits/stdc++.h>
using namespace std;
struct con{
	int ai,bi;
}a[10000000];

bool cmp(con a,con b){
	return a.bi<b.bi;
}

int main()
{
	int n,ans=0,s=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].ai>>a[i].bi;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){//开始比赛的时间必须小于上一次结束比赛的时间 
		if(s<=a[i].ai){
			ans++;
			s=a[i].bi;
		} 
	}
	cout<<ans;
	return 0;
}

7.P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G

见洛谷p1090

看不懂,用c++特性的stl中优先队列
#include<bits/stdc++.h>
#include<queue>
using namespace std;
int a,p=1,s;

int main()
{
	int n,ans=0,s=0;
	cin>>n;
	priority_queue<int ,vector<int> ,greater<int> >q;
	for(int i=1;i<=n;i++){
		cin>>a;
		q.push(a);
	}
	for(int i=1;i<n;i++){
		a=q.top();
		q.pop();
		a+=q.top();
		q.pop();
		s+=a;
		q.push(a);
	}
	cout<<s;
	return 0;
}

8.P1031 [NOIP2002 提高组] 均分纸牌

见洛谷p1031

1.算平均数
2.每堆纸牌与平均数的关系
3.a[i+1] -= sum - a[i]; 负数也可以刚,完毕
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int a[100000],n,sum,cnt;


int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
	}
	sum/=n;
	for(int i=1;i<n;i++){
		if(a[i]!=sum){
			a[i+1] -= sum - a[i];
			cnt++;
		}
	}
	cout<<cnt++;
	return 0;
}

十.动态规划


1.P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles

见洛谷p1216

学习dp的简单题型
可以分2种做法
//自下而上,只需要知道最下面一排的数值,每次通过比两个数的大小,求出最后最大的数
#include<iostream>
#include<algorithm>
using namespace std;
int r;
int f[1050][1050],a[1050][1050];

int main()
{
	cin>>r;
	for(int i=1;i<=r;i++){
		for(int j=1;j<=i;j++){
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=r;i++){
		for(int j=1;j<=i;j++){
			f[r][j]=a[r][j];
		}
	}
	for(int i=r;i>=1;i--){
		for(int j=1;j<=i;j++){
			f[i][j]=max(f[i+1][j+1]+a[i][j],f[i+1][j]+a[i][j]);
		}
	}
	cout<<f[1][1];
    return 0;
}
//代码相对较少
#include<iostream>
#include<algorithm>
using namespace std;
int r;
int f[1050][1050],a[1050][1050];

int main()
{
	cin>>r;
	for(int i=1;i<=r;i++){
		for(int j=1;j<=i;j++){
			cin>>f[i][j];
		}
	}
	for(int i=r;i>=1;i--){
		for(int j=1;j<=i;j++){
			f[i][j]+=max(f[i+1][j+1],f[i+1][j]);
		}
	}
	cout<<f[1][1];
    return 0;
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值