寒假训练第一周总结
- 这一周有三次比赛,有许多题都不能很快的有思路,那些算法自己都没有学过不会用,写起来非常吃力,我决定通过比赛了解有哪些算法自己慢慢学习。
[NOIP2005 普及组] 采药
题目描述
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
输入格式
第一行有 $2$ 个整数 $T$($1 \le T \le 1000$)和 $M$($1 \le M \le 100$),用一个空格隔开,$T$ 代表总共能够用来采药的时间,$M$ 代表山洞里的草药的数目。
接下来的 $M$ 行每行包括两个在 $1$ 到 $100$ 之间(包括 $1$ 和 $100$)的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出格式
输出在规定的时间内可以采到的草药的最大总价值。
样例 #1
样例输入 #1
70 3
71 100
69 1
1 2
样例输出 #1
3
提示
【数据范围】
- 对于 $30%$ 的数据,$M \le 10$;
- 对于全部的数据,$M \le 100$。
【题目来源】
NOIP 2005 普及组第三题
解析:
本题是一个(动态规划)背包问题也是我第一次遇到,看了网上的教学视频后才知道这个方法。
所谓背包问题的解答:首先建立一个二维数组,第一行第一列都为0,从a[1][1]开始判断编号为1;容量为1时背包能装入的最大值,分两种情况一、如果装不下当前物品,那么前n个物品的最佳组合和前n-1给物品的最佳组合是一样的。二、如果装得下当前物品,1.装当前物品,在给当前物品预留了相应空间的情况下,前n-1个物品的最佳组合加上当前物品的价值就是总价值。2.不装当前物品,那么前n-1个物品和前n个物品的最佳组合是一样的;选取较大的价值,就是当前最佳组合的价值。
`#include<stdio.h>
int max(int a,int b);
int main(void){
int t,m;
int f[110][1100];
int w[110],v[110];
scanf("%d%d",&t,&m);
for(int i=1;i<=m;i++){//i从1开始取i为0时其任意数组的值都为0;
scanf("%d%d",&w[i],&v[i]);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=t;j++){
if(w[i]>j){//第i件物品大于背包容量
f[i][j]=f[i-1][j];
}
else {//第i件物品小于背包容量,判断装与不装价值大小
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
}
}
}
printf("%d",f[m][t]);
return 0;
}
int max(int a,int b ){
int x;
x=(a>b?a:b);
return x;
}
`
2.
标题计数
题目背景
5ab 试图帮洛谷写机器人,数题解中有多少个一级标题。
题目描述
Markdown 是一种标记语言。在 Markdown 中,若一行的第一个非空白字符是井号(#),且紧跟着若干个空格,则这一行剩余的非空白内容将会按照一级标题渲染。
在本题范围内,下面的都是一级标题:
# This is a title
# This is another title
# This is also a title
# You#can#add#more#sharps
# #
在本题范围内,下面的都不是一级标题:
<h1>an HTML title</h1>
#You should insert a space
## This is a secondary title
aaaaa # This is not a title at all
#
You should add something after the sharp sign
给定一段多行文本,求出这段文本总共有多少个一级标题。
输入格式
第一行输入一个整数 $n$,代表文本的行数。
接下来输入 $n$ 行,是给出的标记文本。
输出格式
输出一行一个整数,为这段文本中的一级标题个数。
样例 #1
样例输入 #1
1
#u#n#t#i#t#l#e#d#
样例输出 #1
0
样例 #2
样例输入 #2
1
# a perfect title
样例输出 #2
1
样例 #3
样例输入 #3
10
# a
# b
## c
#d
#
e
# f#g#h#i#j
##k
# #
l # m
样例输出 #3
4
提示
样例 3 解释
第 2,3,8,10 行(文本第 1,2,7,9 行)是满足条件的一级标题。
如果选手在比赛中使用 Windows 系统,则直接从网站或下发题面中复制的样例的换行符是 CRLF,与真实数据中的 LF 会有区别。为了方便调试,建议使用下发文件中的样例进行测试,并直接使用文件输入输出。
数据规模与约定
总文本不超过 $100$ 个字符,不超过 $10$ 行。文本中只有英文字母,井号(#),换行符(Line Feed,LF,\n)和空格。
解析:先判断前面字符是否为空格或者井号,空格继续,井号继续进入新循环判断,如果紧接着不是空格跳出循环;如果碰到非空格标识符c加1记录;如果一直为空格,到达'\0'退出循环判断下一个字符串;
代码:`#include<stdio.h>
int main(){
int i,j,n,t,c=0,x=0;
char a[10000]={0};
scanf("%d",&n);
getchar();//**注意用gets()时加getchar()**
for(i=0;i<n;i++){
gets(a);
for(j=0;a[j]!='\0';j++){
if(x==1){
x=0;
break;
}
if(a[j]==' '){
continue;
}
else if(a[j]=='#'){
for(t=j+1;a[t]!='\0';t++){
if((t==j+1)&&(a[t]!=' ')){
x=1;
break;
}
if(a[t]==' ') continue;
if(a[t]!=' ') {
c++;
x=1;
break;
}
}
}
else break;
}
}
printf("%d\n",c);
return 0;
}
`
[蓝桥杯 2017 省 AB] 分巧克力
题目描述
儿童节那天有 $K$ 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 $N$ 块巧克力,其中第 $i$ 块是 $H_i \times W_i$ 的方格组成的长方形。
为了公平起见,小明需要从这 $N$ 块巧克力中切出 $K$ 块巧克力分给小朋友们。切出的巧克力需要满足:
-
形状是正方形,边长是整数。
-
大小相同。
例如一块 $6 \times 5$ 的巧克力可以切出 $6$ 块 $2 \times 2$ 的巧克力或者 $2$ 块 $3 \times 3$ 的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小 $H_i$ 计算出最大的边长是多少么?
输入格式
第一行包含两个整数 $N$ 和 $K$。$(1 \le N,K \le 10^5)$。
以下 $N$ 行每行包含两个整数 $H_i$ 和 $W_i$。$(1 \le H_i,W_i \le 10^5)$。
输入保证每位小朋友至少能获得一块 $1 \times 1$ 的巧克力。
输出格式
输出切出的正方形巧克力最大可能的边长。
样例 #1
样例输入 #1
2 10
6 5
5 6
样例输出 #1
2
提示
蓝桥杯 2022 省赛 A 组 I 题。
解析:切出巧克力最大边长为100000,最小为1;
将每块巧克力的长宽记录下来,若h为长,w为宽,mid为切出正方形的边长,第i块巧克力能切出h/mid*w/mid块巧克力;
通过二分(二分可以大大缩短查找时间)找到刚好等于小朋友人数的边长的巧克力;
代码:
`#include<stdio.h>
int h[100000];
int w[100000];
int main(){
int n,k,i,c=0,max=100000,min=1;
scanf("%d%d",&n,&k);
for(i=0;i<n;i++){
scanf("%d%d",&h[i],&w[i]);
}
while(min<=max){
int mid=(max+min)/2;
int cnt=0;
for(i=0;i<n;i++){
cnt+=(h[i]/mid)*(w[i]/mid);
}
if(cnt>=k){
min=mid+1;
c=mid;
}
else{
max=mid-1;
}
}
printf("%d",c);
return 0;
}`
·通过其他的题目还了解到,如果测试数据小可以打表(如约瑟夫),有些题目如果你了解到他的意思,还可以用数学公式来很快的解决(如毕业后)。
浙公网安备 33010602011771号