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