Week4-CSP-M1

A-咕咕东的奇遇

题目描述

咕咕东是个贪玩的孩子,有一天,他从上古遗迹中得到了一个神奇的圆环。这个圆环由字母表组成首尾相接的环,环上有一个指针,最初指向字母a。咕咕东每次可以顺时针或者逆时针旋转一格。例如,a顺时针旋转到z,逆时针旋转到b。咕咕东手里有一个字符串,但是他太笨了,所以他来请求你的帮助,问最少需要转多少次。

Input

输入只有一行,是一个字符串。

Outout

输出最少要转的次数。

Sample input

zeus

Sample output

18

解题思路

  • 每次旋转到一个字母有顺时针、逆时针两种方法
  • 每次的转法对下一次不影响,所以使每一次转的次数都最短即可
  • 看两个点的ASC码差值的绝对值,小于一半(13)则“直接转”,大于一半(13)则从模(26)-差值的方向转。将每次转的次数累和即可。

完整代码

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string a;
	cin>>a;
	int count=0;
	int m;
	int length=a.length();
	for(int i=0;i<length;i++)
	{	if(i==0)
		{m=a[i]-'a';}
		else
		m=a[i]-a[i-1];
		if(m<0)
		m=-m; 
		if(m<=13)
			count=count+m;
		else
			count=count+26-m;
	
	}
	cout<<count<<endl;



}

B-咕咕东想吃饭

题目描述

咕咕东考试周开始了,考试周一共有n天。他不想考试周这么累,于是打算每天都吃顿好的。他决定每天都吃生煎,咕咕东每天需要买a_iai​个生煎。但是生煎店为了刺激消费,只有两种购买方式:①在某一天一次性买两个生煎。②今天买一个生煎,同时为明天买一个生煎,店家会给一个券,第二天用券来拿。没有其余的购买方式,这两种购买方式可以用无数次,但是咕咕东是个节俭的好孩子,他训练结束就走了,不允许训练结束时手里有券。咕咕东非常有钱,你不需要担心咕咕东没钱,但是咕咕东太笨了,他想问你他能否在考试周每天都能恰好买a_iai​个生煎。

Input

输入两行,第一行输入一个正整数n(1<=n<=100000)(1<=n<=100000),表示考试周的天数。第二行有n个数,第i个数a_i(0<=a_i<=10000)ai​(0<=ai​<=10000)表示第i天咕咕东要买的生煎的数量。

Output

如果可以满足咕咕东奇怪的要求,输出"YES",如果不能满足,输出“NO”。(输出不带引号)

Sample input 1

4
1 2 1 2

Sample output 1

YES

Sample input 2

3
1 0 1

Sample ouput 2

NO

解题思路

  • 手中券的情况仅两种:1张,0张,多的可以用方案1代替
  • 只需要看最后一天有没有剩余券即可
  • 每天储存上一天的剩余券数,通过判断(今天的生煎-昨天的余券)%2判断今天有没有剩余券,不断递归,直到最后一天买完生煎。判断有没有券剩余即可。
  • 注意特殊值0:某一天为0的话则方案一二都无法满足,无法继续;
    -注意YES,NO是全大写

完整代码

//券有效情况仅两种:1张,0张,多的可以用方案1代替
//看最后一天有没有剩余券 
#include<iostream>
using namespace std;
int main(){
	int n;
	cin>>n;
	int a[100100];
	for(int i=0;i<n;i++)
		cin>>a[i];
	bool use=false;
	for(int i=0;i<n;i++)
	{	if(a[i]==0)
	{//一天不吃生煎,两种策略无法实现 
			cout<<"NO"<<endl;
			return 0;
		}
		if(use==false)
			{if(a[i]%2==1)
				use=true;}
		else
			{if((a[i]-1)%2==0)
				use=false;}
			
	
	}

		if(use==true)
			cout<<"NO"<<endl;
		else
			cout<<"YES"<<endl;


}

C-可怕的宇宙射线

题目描述

众所周知,瑞神已经达到了CS本科生的天花板,但殊不知天外有天,人外有苟。在浩瀚的宇宙中,存在着一种叫做苟狗的生物,这种生物天生就能达到人类研究生的知识水平,并且天生擅长CSP,甚至有全国第一的水平!但最可怕的是,它可以发出宇宙射线!宇宙射线可以摧毁人的智商,进行降智打击!
宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),初始方向默认向上。宇宙射线会在发射出一段距离后分裂,向该方向的左右45°方向分裂出两条宇宙射线,同时威力不变!宇宙射线会分裂 次,每次分裂后会在分裂方向前进ai个单位长度。现在瑞神要带着他的小弟们挑战苟狗,但是瑞神不想让自己的智商降到普通本科生zjm那么菜的水平,所以瑞神来请求你帮他计算出共有多少个位置会被"降智打击"。

Iuput

输入第一行包含一个正整数 n(n<=30),表示宇宙射线会分裂n 次
第二行包含n个正整数a1,a2···an ,第ai 个数表示第 i次分裂的宇宙射线会在它原方向上继续走多少个单位长度

Output

输出一个数ans ,表示有多少个位置会被降智打击

Sample input

4
4 2 2 3
12

Sample output

39
1

解题思路

  • 本题难在方向多变,一共8个方向,想不到用数组记录,通过加减取余联系的话会比较复杂。
  • 用四维数组vis记录当前坐标(x,y),第t次分裂,方向。
  • 用二维数组mark记录所有到达过的点,防止重复。
  • 用二维数组dir记录当前行代表的方向的下一个点的x,y。(此方法比较难想)
  • dfs不断往下遍历,分裂次数到了即不再向下遍历。每次到达的点判断一下之前是否到过,没到过则ans++。

注意事项

  • 每次在本方向上前进的长度k是本方向两点间距离的k倍,不是绝对长度k(考试时没认真看图误以为绝对长度k,最后算一堆小数,无法判断是否落在整数坐标点上,从而失败)
  • dfs时要判断当前位置是否已到达、是否需要继续往下遍历。

完整代码

#include<cstdio>
int ans=0;
	int vis[330][330][31][8],mark[330][330],n,a[35];
	//vis[x][y][第i次分裂][延伸方向]
	//mark判断当前点是否到达过
	int dir[8][2]=
	{{1,0},//0代表右 
	 {1,1},//1代表右上 
	 {0,1},//2代表上 
	 {-1,1},//3代表左上 
	 {-1,0},//4代表左 
	 {-1,-1},//5代表左下 
	 {0,-1},//6代表下 
	 {1,-1}//7 代表右下 
}; //0到7刚好是逆时针走一圈,所以对每个方向,下一分裂方向为当前方向+1、当前方向+7,再分别对8取余 

void dfs(int x,int y,int t,int d)
{
	if(vis[x][y][t][d]==1)//当前位置到达过了 
		return;
	vis[x][y][t][d]=1;//标记为到达 
	
	for(int i=1;i<=a[t];i++)//a[t]是长度
	{x=x+dir[d][0];
	 y=y+dir[d][1];
	 if(mark[x][y]==0)//之前没加入这个点
	 	{ans++;
		 mark[x][y]=1;}}
		 
	if(t<n)//还没遍历完
	{dfs(x,y,t+1,(d+1)%8);
	 dfs(x,y,t+1,(d+7)%8);} 



}
int main()
{

	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	dfs(160,160,1,2);
	printf("%d",ans);





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值