牛客小白月赛88(A~D题解)

文章讲述了如何在牛客网的编程问题中,利用贪心策略和动态规划的方法,选择最少数量且总诱惑力足够的食物来捕捉超级闪光牛可乐,同时考虑食物数量限制。
摘要由CSDN通过智能技术生成

如果我还没更后四道题的题解,麻烦call我一下

A.超级闪光牛可乐

链接:https://ac.nowcoder.com/acm/contest/75771/A
来源:牛客网

  • 森林中出现了野生的超级闪光牛可乐!想要捕捉它,你至少需要投喂 x 点诱惑力的食物。幸运的是,清楚姐姐在知道了这件事后,非常大气的为你开放了她的豪华零食仓库——仓库里有 n 种不同名称的食物,第 i 种食物能提供 w i w_i wi点的诱惑力。当你所投喂食物的诱惑力之和不小于 x 时,就可以顺利的捕捉到它。现在,你可以从仓库中取走一些食物了,不管怎么说,今天的目标只有一个,那就是拿下超级闪光牛可乐!

输入输出:

  • 每个测试文件仅有一组测试数据。第一行输入一个整数 x ( 1 ≤ x ≤ 1000 1 \le x \le 1000 1x1000) 表示至少需要多少诱惑力的食物才能捕捉这一只超级闪光牛可乐。第二行输入一个整数 n ( 1 ≤ n ≤ 26 1 \le n \le 26 1n26) 表示清楚姐姐豪华零食仓库中的零食种类数量。随后 n 行,每行输入一个小写字母 ch 和一个整数 w ( ′ a ′ ≤ c h ≤ ′ z ′ , 1 ≤ w ≤ 500 ) ({\rm 'a'} \le ch \le {\rm 'z'}, 1 \le w \le 500) (achz,1w500) ,表示第 i 种零食的名称以及提供的诱惑力。保证零食的名称不重复;使用单个空格间隔。

  • 你需要在一行上输出一个由小写字母组成的答案字符串,代表你要喂给超级闪光牛可乐的食物。但是请注意,喂食的零食数量不能超过 1000 个,否则牛可乐会因为吃不下而直接离开。清楚姐姐仓库中没有的零食种类提供的诱惑力会被视为 0 。如果无法捕获牛可乐,仅需输出一行 −1 。

解题:

\qquad 这道题非常的神奇。
\qquad 请读者仔细读题3遍以上,尤其注意它的数据范围。
\qquad 读好了吗

由于x是1000的上限,但是没有为0诱惑力的零食。说明,只要有零食,那么这个零食投喂1000次一定会把这个牛可乐吸引到,所以输出1000次第一个零食就是答案

#include<iostream>
using namespace std;
int main(){
	int a,b;
	cin>>a>>b;
	char c;
	cin>>c;
	for(int i=1 ;i<=1000; ++i)cout<<c;
	
	return 0;
}

这个题非常的离谱,如果你看清楚了大概需要一分钟写码。
你不能没看清 如果你没看清可以当个老实人,那么这就是一个贪心的思想,直接拿出最好吃的把牛可乐填鸭。

#include<iostream>
#include<algorithm>
using namespace std;
const int N=50;
struct node{
	char name;
	int w;
};
node cnm[N];
bool cmp(node a, node b){
	return a.w>b.w;
}
int main(){
	int p;
	cin>>p;
	int n;
	cin>>n;
	
	for(int i=1; i<=n; ++i){
		cin>>cnm[i].name>>cnm[i].w;
		getchar();
	}
	
	sort(cnm+1, cnm+n+1, cmp);
	
	if(p/cnm[1].w>1000 ||(p/cnm[1].w==1000 && p%cnm[1].w!=0)){
		cout<<-1<<endl;
		return 0;
	}
	
	while(p>0){
		cout<<cnm[1].name;
		p-=cnm[1].w;
	}
	return 0;
}

B.人列计算机

链接:https://ac.nowcoder.com/acm/contest/75771/B
来源:牛客网

题目略。

思路

符号,其他符号全都不读,只读入所有的数字,并对与非或的特殊符号去更新mode,那么最后与非或三个门的输入所在的字符串的位置是一定的,直接模拟……

#include<iostream>
#define a str[1]
#define b str[2]
#define d str[3]
#define c str[1]
using namespace std;
char str[30];
int main(){
	int i=0;
	int mode=0;//默认非门 
	while((str[++i]=getchar())!=EOF){
		if(str[i]>='0' && str[i]<='9');
		else{
			if(str[i]=='&')mode=1;
			if(str[i]=='>')mode=2;
			i--;
		}
	}

	if(mode==1){
		if(a=='1' && b=='1'){
			cout<<1;
		}else cout<<0;
		return 0;
	}
	if(mode==2){
		if(a=='1' || d=='1'){
			cout<<1;
		}else cout<<0;
		return 0;
	}
	if(mode==0){
		if(c=='1'){
			cout<<0;
		}
		else cout<<1;
		return 0;
	}
	return 0;
}

C 时间管理大师

来源:牛客网
链接:https://ac.nowcoder.com/acm/contest/75771/C

题目略

思路

数据范围可以知道必定发生在一天内,所以直接转换成分钟,-1,-3,-5,然后排序后去重后输出即可。

#include<iostream>
#include<algorithm>
using namespace std;
#define time h*60+m
const int N=1000*3+100;
int t[N],s[N];
int main(){
	int n;
	cin>>n;
	int ti=0;
	for(int i=1; i<=n; ++i){
		int h, m;
		cin>>h>>m;
		t[++ti]=time-1;
		t[++ti]=time-3;
		t[++ti]=time-5;
	}
	sort(t+1, t+ti+1);
	int la=-1;
	int j=0;
	for(int i=1; i<=ti; ++i){
		if(la==t[i])continue;
		else s[++j]=t[i];
		la=t[i];
	}
	cout<<j<<endl;
	for(int i=1; i<=j; ++i){
		cout<<s[i]/60<<' '<<s[i]%60<<endl;
	}
	return 0;
}

D.我不是大富翁

链接:https://ac.nowcoder.com/acm/contest/75771/D
来源:牛客网

我看大佬们的思路写出来的code都好短,真羡慕毁了

思路:

初始位置是1,为了更好的mod求当前位置,我们把每个位置的编号都减一,使其变成0~n-1。
众所周知,一个地点跳到下一个地点只有两种跳法。而同时地图是有限的,所以无论你怎么跳都在一个圆环内。

首先,你需要对每次起跳做一个初始化,毕竟这个小兄弟一蹦两三圈,你需要等效到蹦一圈就可以了。

那么可以推出一个公式
若在第 i 步,到达 j 位置所需要的步数是 k 令 f i , j = k 那么会有以下公式 : { f i , j = f i − 1 , ( j − d i + n ) % n f i , j = f i − 1 , ( j + d i + n ) % ) n 为了使上式更好的写成 c o d e ,使用这样的表示 f i − 1 , j { f i , ( j + d i − 1 ) % n = f i − 1 , j + 1 ; f i , ( j − d i − 1 + n ) % n = f i − 1 , j + 1 ; 若在第i步,到达j位置所需要的步数是k \\令f_{i,j}=k \\那么会有以下公式: \\ \begin{cases} f_{i,j}=f_{i-1, (j-d_i+n)\%n} \\f_{i,j}=f_{i-1, (j+d_i+n)\%)n} \end{cases} \\为了使上式更好的写成code,使用这样的表示 \\f_{i-1, j}\begin{cases} f_{i, (j+d_{i-1})\%n}=f_{i-1, j}+1; \\f_{i, (j-d_{i-1}+n)\%n}=f_{i-1, j}+1; \end{cases} 若在第i步,到达j位置所需要的步数是kfi,j=k那么会有以下公式:{fi,j=fi1,(jdi+n)%nfi,j=fi1,(j+di+n)%)n为了使上式更好的写成code,使用这样的表示fi1,j{fi,(j+di1)%n=fi1,j+1;fi,(jdi1+n)%n=fi1,j+1;
如果在 f m , 0 f_{m, 0} fm,0的位置上是步数m,那么满足要求。
那么直接进行一个二维的假的动态规划求解就好了

#include<iostream>
using namespace std;
const int N=5500;
int dp[N][N];
int d[N];

int main(){
	int n, m;
	cin>>n>>m;
	
	for(int i=1; i<=m; ++i){
		cin>>d[i];
		d[i]%=n;
	}
	for(int i=0; i<n; ++i)dp[0][i]=0;
	dp[0][0]=1;
	
	for(int i=0; i<m; ++i){
		for(int j=0; j<n; ++j){
			if(dp[i][j]!=0){
		//		cout<<(j+d[i+1])%n<<' '<<(j-d[i+1])%n<<endl;
				dp[i+1][(j+d[i+1]+n)%n]=dp[i][j]+1;
				dp[i+1][(j-d[i+1]+n)%n]=dp[i][j]+1;
				
			}
		}

	}
	if(dp[m][0]==m+1)cout<<"yes";
	else cout<<"no";
	return 0;
}
  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值