CSP-M1

咕咕东的奇遇

题目描述

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

输入格式

输入只有一行,是一个字符串。
输出格式
输出最少要转的次数。

样例输入

zeus

样例输出

18
在这里插入图片描述

做法

每次转转盘有两种选择:顺时针或逆时针。每次找下一个字符时选择格数较少的方向,最后得到的一定是最少要转的次数。
代码中,g1,g2表示当前字符与下一个字符的格数,由于不确定大小,取绝对值。圆盘一共有26格,如果顺时针走g1格,那么逆时针就需要走26-g1格,反之亦然。

代码

#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;


int main()
{
	char c[10009];
	cin.getline(c,10009);
	int n=strlen(c);
	int c1='a';
	int s=0;
	for(int i=0;i<n;i++)
	{
		int a1=c[i];
		int g1=abs(a1-c1);
		int g2=26-abs(a1-c1);
		if(g1>g2)
		s=s+g2;
		else
		s=s+g1;
		c1=c[i];
	}
	cout<<s<<endl;
	return 0;
}

咕咕东想吃饭

题目描述

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

输入格式

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

输出格式

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

样例输入1

4
1 2 1 2

样例输出1

YES

样例输入2

3
1 0 1

样例输出2

NO

做法

如果当天吃的生煎个数是偶数,(0除外)可以选择①如果有券必须用券,买奇数个,得到一张新券②没有券,直接买偶数个。
如果当天吃的生煎个数是奇数,可以选择①有券必须用券,买偶数个②没有券,买奇数个,得到一张券。
用q=1/0,表示是否有前一天的券。当天不吃生煎,并且还有前一天的券时,券就不能用了,说明无法达到要求。

代码

#include<iostream>
using namespace std;

int main()
{
	int n;
	cin>>n;
	int q=0;
	int a[100009];
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	for(int i=0;i<n;i++)
	{
		if(q==0&&a[i]%2==1)
		{
			q=1;
			continue;
		}
		if(q==1&&a[i]%2==1)
		{
			q=0;
			continue;
		}
		if(q==1&&a[i]==0)
		{
			break;
		}
	}
	if(q!=0)
	 cout<<"NO"<<endl;
	else
	 cout<<"YES"<<endl;
	return 0;
}

可怕的宇宙射线

题目描述

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

输入描述

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

输出描述

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

样例输入

在这里插入图片描述

样例输出

在这里插入图片描述在这里插入图片描述

做法

bfs剪枝
结构体coo保存每个出发点的坐标x,y;要走的方向d,和层数l。d一共有上下左右、左上、左下……8个方向,取值为0-7.
在这里插入图片描述
如图,当出发点的方向是0即向上时,分裂点有1,7两个方向,以此类推,可以采用对8取余的方式确定分裂射线的方向。
借助队列完成bfs,将起点入队,每次从队列中取出一点,累加覆盖的坐标个数,将新的出发点入队。当队列首元素层数达到n时,说明分裂完毕。
题目数据范围比较大,需要考虑剪枝,当出发点的层数,坐标,方向有重复时,无需重复进行分裂,可以用map完成一对一的映射。

代码

#include<iostream>
#include<string.h>
#include<queue> 
#include<map>
using namespace std;

int mark[1000][1000];
int xx[]={0,1,1,1,0,-1,-1,-1};
int yy[]={1,1,0,-1,-1,-1,0,1};

struct coo
{
	int x,y;
	int d;//方向
	int l;//层数 
	
	bool operator<(const coo &a) const
	{
	    if(x!=a.x) return x<a.x;
		if(y!=a.y) return y<a.y;
		if(d!=a.d) return d<a.d;
		return l<a.l;

	}
};

map<coo,bool> mp;

int main()
{
	memset(mark,0,sizeof(mark));
	int n;
	cin>>n;
	int a[32];
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	coo s;
	s.x=500;
	s.y=500;
	s.d=0;
	s.l=1;
	int num=a[1];
	for(int i=0;i<a[1];i++)
	{
		mark[500][500+i]=1;
	}
	s.y=500+num;
	queue<coo> qu;
	qu.push(s);
	while(!qu.empty())
	{
		coo t=qu.front();
		if(t.l==n)
		{
			cout<<num<<endl;
			break;
		}
		
		if(mp[t])
		{
			qu.pop();
			continue;
		}
	    
	    mp[t]=true;
	    
		for(int j=-1;j<2;j=j+2)//每个点有两个方向可以走 
		{
			coo t1=t;
			int m=t1.l+1;
			for(int i=0;i<a[m];i++)
			{
			t1.x=t1.x+xx[(t1.d+j+8)%8];
			t1.y=t1.y+yy[(t1.d+j+8)%8];
			if(mark[t1.x][t1.y]==0)
			{
				mark[t1.x][t1.y]=1;
				num++;
			}
		    }
		    
		    t1.l=m;
		    t1.d=(t1.d+j+8)%8;
			qu.push(t1);
		}
		
		qu.pop();
	}
	return 0;
}
发布了6 篇原创文章 · 获赞 0 · 访问量 85

猜你喜欢

转载自blog.csdn.net/weixin_44359234/article/details/104976416
今日推荐