程序设计思维与实践 CSP-M1 补题 (3/4/数据班)

A 咕咕东的奇遇

题目

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

Input

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

Output

输出最少要转的次数。

Examples

Input
zeus

Output
18

思路

分别计算每一个字母顺时针和逆时针旋转的次数,将较小值加入到结果中即可

实现代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
char a[10005];
char b[26]={'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'};

int main()
{
	cin>>a;
	int len=strlen(a);
	int cur=0;
	int index=0;
	int zhen=0;
	int ni=0;
	int res=0;
	for(int i=0;i<26;i++)
	{
		if(a[0]==b[i])
		{
			index=i;
			break;
		}
	}
	zhen=index;
	ni=26-index;
	int minn=min(zhen,ni);
	res=res+minn;
	int index2=0;
	for(int i=1;i<len;i++)
	{
		for(int j=0;j<26;j++)
		{
			if(b[j]==a[i])
			{
				index2=j;
				break;
			}
		}
		zhen=abs(index2-index);
		ni=26-abs(index2-index);
		minn=min(zhen,ni);
		res=res+minn;
		index=index2;
	}
	cout<<res;
	return 0;
}

B 咕咕东想吃饭

题目

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

Input

输入两行,第一行输入一个正整数n(1<=n<=100000),表示考试周的天数。

第二行有n个数,第i个数ai(0<=ai<=10000)ai表示第i天咕咕东要买的生煎的数量。

Output

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

Examples

Input1
4
1 2 1 2

Output1
YES

Input2
3
1 0 1

Output2
NO

思路

购买生煎可以分为以下三种情况:
(1)今天不买,若没有剩余的卷,则继续进行;若卷仍有剩余,则不满足题目的要求,输出“NO”
(2)今天购买的生煎数为奇数,若没有剩余的卷,则选择第二种购买方式,此时剩余一张卷;若卷仍有剩余,则直接使用卷购买
(3)今天购买的生煎数为偶数,若没有剩余的卷,则选择第一种购买方式,卷的数量没有变化;若卷仍有剩余,则先使用卷购买一个,然后选择第二种购买方式,此时剩余一张卷

若最后卷仍有剩余,则输出“NO”;
若最后卷没有剩余,则输出"YES".

实现代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[100005];
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	bool yu=false;
	bool res=true;
	for(int i=0;i<n;i++)
	{
		if(a[i]==0)
		{
			if(yu==false) continue;
			if(yu==true)
			{
				cout<<"NO";
				return 0;
			}
		}
		if(a[i]>0)
		{
			if(a[i]%2==0)
			{
				if(yu==false) yu=false;
				else yu=true;
			}
			if(a[i]%2==1)
			{
				if(yu==false) yu=true;
				else yu=false;
			}
		}
	}
	if(yu==false) res=true;
	if(yu==true) res=false;
	if(res==true) cout<<"YES";
	if(res==false) cout<<"NO";
	return 0;
}

总结

(1)误以为每次只能选择一种购买方式((ꐦ ´͈ ᗨ `͈ )看题啊,不然ai>2时怎么买
(2)当天的卷必须在第二天使用,不能不用,所以通过卷是否有剩余来判断是“YES”还是“NO”。

C 可怕的宇宙射线

题目

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

Input

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

Output

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

Examples

Input
4
4 2 2 3
Output
39

在这里插入图片描述

思路

(1)如果使用普通的DFS,时间复杂度过高,造成TLE
(2)可以利用一个四维数组进行剪枝处理,记录该点在第几次的分裂过程中的分裂方向。
(3)若当前状态已经到达过,则说明回到起点,结束递归
(4)在进行方向的说明时,通过偏移量数组实现,减少代码的冗余

实现代码

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

bool vis[500][500][31][8]={0};
bool flag[500][500]={0};
int n,res=0;
int fx[8]={0,1,1,1,0,-1,-1,-1};
int fy[8]={1,1,0,-1,-1,-1,0,1};
int a[35];

void dfs(int x,int y,int num,int f)
{
	if(vis[x][y][num][f]==1) return;
	vis[x][y][num][f]=1;
	for(int i=0;i<a[num];i++)
	{
		x=x+fx[f];
		y=y+fy[f];
		if(flag[x][y]==0) 
		{
			res++;
			flag[x][y]=1;	
		}
	}
	if(num<n)
	{
		if(f==0)
		{
			dfs(x,y,num+1,1);
			dfs(x,y,num+1,7);
		}
		else if(f==1)
		{
			dfs(x,y,num+1,0);
			dfs(x,y,num+1,2);
		}
		else if(f==2)
		{
			dfs(x,y,num+1,1);
			dfs(x,y,num+1,3);
		}
		else if(f==3)
		{
			dfs(x,y,num+1,2);
			dfs(x,y,num+1,4);
		}		
		else if(f==4)
		{
			dfs(x,y,num+1,3);
			dfs(x,y,num+1,5);
		}
		else if(f==5)
		{
			dfs(x,y,num+1,4);
			dfs(x,y,num+1,6);		
		}
		else if(f==6)
		{
			dfs(x,y,num+1,5);
			dfs(x,y,num+1,7);		
		}	
		else if(f==7)
		{
			dfs(x,y,num+1,0);
			dfs(x,y,num+1,6);		
		}			
	}
}

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	dfs(200,200,1,0);
	cout<<res<<endl;
	return 0;
}

总结

(1)知道利用DFS实现,但没有进行剪枝,暴力还写错了ㄒoㄒ
(2)做题时注意时间复杂度的分析,防止TLE

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值