A 咕咕东的奇遇
题意
题目描述
咕咕东是个贪玩的孩子,有一天,他从上古遗迹中得到了一个神奇的圆环。这个圆环由字母表组成首尾相接的环,环上有一个指针,最初指向字母a。咕咕东每次可以顺时针或者逆时针旋转一格。例如,a顺时针旋转到z,逆时针旋转到b。咕咕东手里有一个字符串,但是他太笨了,所以他来请求你的帮助,问最少需要转多少次。
加个示意图
输入格式
输入只有一行,是一个字符串。
输出格式
输出最少要转的次数。
样例输入
zeus
样例输出
18
数据点 字符串长度
1,2 小于等于10
3,4,5 小于等于100
6,7,8,9,10 小于等于10000
做法
贪心,每次选择顺时针或逆时针差距最小的作为步长。
代码
#include<iostream>
using namespace std;
string s;
int main()
{
cin>>s;
char temp='a';
int ssz,nsz,ans=0;
for(int i=0;i<s.length();i++)
{
ssz=abs(s[i]-temp);
nsz=26-ssz;
ans+=min(ssz,nsz);
// cout<<ssz<<" "<<nsz<<endl;
temp=s[i];
}
cout<<ans<<endl;
}
B 咕咕东想吃饭
题意
题目描述
咕咕东考试周开始了,考试周一共有n天。他不想考试周这么累,于是打算每天都吃顿好的。他决定每天都吃生煎,咕咕东每天需要买a_ia
i
个生煎。但是生煎店为了刺激消费,只有两种购买方式:①在某一天一次性买两个生煎。②今天买一个生煎,同时为明天买一个生煎,店家会给一个券,第二天用券来拿。没有其余的购买方式,这两种购买方式可以用无数次,但是咕咕东是个节俭的好孩子,他训练结束就走了,不允许训练结束时手里有券。咕咕东非常有钱,你不需要担心咕咕东没钱,但是咕咕东太笨了,他想问你他能否在考试周每天都能恰好买a_ia
i
个生煎。
输入格式
输入两行,第一行输入一个正整数n(1<=n<=100000)(1<=n<=100000),表示考试周的天数。
第二行有n个数,第i个数a_i(0<=a_i<=10000)a
i
(0<=a
i
<=10000)表示第i天咕咕东要买的生煎的数量。
输出格式
如果可以满足咕咕东奇怪的要求,输出"YES",如果不能满足,输出“NO”。(输出不带引号)
样例输入1
4
1 2 1 2
样例输出1
YES
样例输入2
3
1 0 1
样例输出2
NO
数据点 n(上限) a_ia
i
(上限)
1,2 10 10
3,4,5 1000 10
6,7 10 10000
8,9,10 100000 10000
做法
也是贪心。注意到奇偶性。
构造如下方法。
在用完前一天优惠券时,若还需要买偶数个生煎,则直接采用1方案。
若有奇数个,则先用1方案,剩一个用2方案。
以上是对第二天影响最小的方案。
代码
#include<iostream>
using namespace std;
int n,a[100009];
int main()
{
cin>>n;
int last=0,temp=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n-1;i++)
{ temp=a[i]-last;
if(temp<0)
{
cout<<"NO"<<endl;
return 0;
}
if(temp%2==0)
{
last=0;
}
else if(temp%2==1)
{
last=1;
}
}
temp=a[n]-last;
if(temp<0)
{
cout<<"NO"<<endl;
return 0;
}
if(temp%2==0)
{
last=0;
cout<<"YES"<<endl;
}
else if(temp%2==1)
{
last=1;
cout<<"NO"<<endl;
}
}
C 宇宙射线
题意
题目描述
众所周知,瑞神已经达到了CS本科生的天花板,但殊不知天外有天,人外有苟。在浩瀚的宇宙中,存在着一种叫做苟狗的生物,这种生物天
生就能达到人类研究生的知识水平,并且天生擅长CSP,甚至有全国第一的水平!但最可怕的是,它可以发出宇宙射线!宇宙射线可以摧毁
人的智商,进行降智打击!
宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),初始方向默认向上。宇宙射线会在发射出一段距离后分裂,向该方向的
左右45°方向分裂出两条宇宙射线,同时威力不变!宇宙射线会分裂 次,每次分裂后会在分裂方向前进 个单位长度。
现在瑞神要带着他的小弟们挑战苟狗,但是瑞神不想让自己的智商降到普通本科生 那么菜的水平,所以瑞神来请求你帮他计算出共有多
少个位置会被"降智打击"
输入描述
输入第一行包含一个正整数 ,表示宇宙射线会分裂 次
第二行包含n个正整数 ,第 个数 表示第 次分裂的宇宙射线会在它原方向上继续走多少个单位长度。
输出描述
输出一个数 ,表示有多少个位置会被降智打击
做法
直接bfs如下面第一份代码,会指数级爆炸。
注意到,每次产生子节点时,是对称的。
最大的重复可能性是,相同子节点下一层的扩展是相同的。
因此考虑到用四维数组记录是否下一层扩展相同,如果已经被扩展了,则不加入bfs。(第二份代码)
代码
朴素bfs(爆内存,指数爆炸)
#include<iostream>
#include<queue>
using namespace std;
bool vis[3300][3300];
int n,a[40],ans,xxx,yyy;
int dx[]={0,1,1,1,0,-1,-1,-1};
int dy[]={1,1,0,-1,-1,-1,0,1};
struct dj{
int num;
int fx;
int x,y;
};
void bfs()
{
dj temp;
temp.num=1;
temp.fx=0;
temp.x=160;
temp.y=160;
queue<dj>q;
q.push(temp);
while(!q.empty())
{
dj now=q.front();
q.pop();
xxx=now.x;
yyy=now.y;
for(int k=1;k<=a[now.num];k++)
{ xxx=xxx+dx[now.fx];
yyy=yyy+dy[now.fx];
if(vis[xxx][yyy]==false)
{
ans++;
vis[xxx][yyy]=true;
}
}
if(now.num<=n)
{
dj n1,n2;
n1.num=now.num+1;
n1.fx=(now.fx+1)%8;
n1.x=xxx;
n1.y=yyy;
n2.num=now.num+1;
n2.fx=(now.fx+7)%8;
n2.x=xxx;
n2.y=yyy;
q.push(n1);
q.push(n2);
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
//cout<<a[i];
}
bfs();
cout<<ans<<endl;
}
剪枝
#include<iostream>
#include<queue>
using namespace std;
bool vis[330][330][40][10];
int n,a[40],ans,xxx,yyy;
int dx[]={0,1,1,1,0,-1,-1,-1};
int dy[]={1,1,0,-1,-1,-1,0,1};
struct dj{
int num;
int fx;
int x,y;
bool operator==(dj&p)
{
if(num==p.num&&fx==p.fx&&x==p.x&&y==p.y)return 1;
else return 0;
}
};
void bfs()
{
dj temp;
temp.num=1;
temp.fx=0;
temp.x=160;
temp.y=160;
queue<dj>q;
q.push(temp);
vis[temp.x][temp.y][temp.num][temp.fx]=true;
while(!q.empty())
{
dj now=q.front();
q.pop();
xxx=now.x;
yyy=now.y;
for(int k=1;k<=a[now.num];k++)
{ xxx=xxx+dx[now.fx];
yyy=yyy+dy[now.fx];
if(vis[xxx][yyy][0][0]==false)
{
ans++;
vis[xxx][yyy][0][0]=true;
}
}
if(now.num<n)
{
dj n1,n2;
n1.num=now.num+1;
n1.fx=(now.fx+1)%8;
n1.x=xxx;
n1.y=yyy;
n2.num=now.num+1;
n2.fx=(now.fx+7)%8;
n2.x=xxx;
n2.y=yyy;
if(vis[n1.x][n1.y][n1.num][n1.fx]==false)
{
vis[n1.x][n1.y][n1.num][n1.fx]=true;
q.push(n1);
}
if(vis[n2.x][n2.y][n2.num][n2.fx]==false)
{vis[n2.x][n2.y][n2.num][n2.fx]=true;
q.push(n2);
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
//cout<<a[i];
}
bfs();
cout<<ans<<endl;
}