咕咕东的奇遇
题目描述
咕咕东是个贪玩的孩子,有一天,他从上古遗迹中得到了一个神奇的圆环。这个圆环由字母表组成首尾相接的环,环上有一个指针,最初指向字母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;
}