第一次csp模拟题目回顾

题目一 咕咕东的奇遇

题目描述

一个圆环包含26个英文字母,顺时针从a到z排列,有一个指针指向a,每次可以顺时针或逆时针旋转一格。如a顺时针旋转到z,逆时针旋转到b。现在有一个字符串(长度<=10000),请输出要得到这个字符串最少需要旋转的次数

input

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

output

输出最少要转的次数。

example

输入

zeus

输出

18

思路与做法

没有什么难度的一道题,保证每次旋转都是最近的,那么总结果就是最近的.可以直接利用字符串的asii码比较远近.

代码

#include <iostream>
#include <string>
#include <cmath> 
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	string tem;
	cin>>tem;
	int sum=0;
	int judge=int('a');
	for(int i=0;i<tem.length();i++)
	{
		int chazhi=abs(int(tem[i])-judge);
		if(chazhi<13)
		{
			sum+=chazhi;
		}
		else sum+=26-chazhi;
		judge=int(tem[i]);
	}
	cout<<sum;
	return 0;
}

题目二

题目描述

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

input

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

output

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

example

input 1

4
1 2 1 2

output 1

YES

input 2

3
101

output 2

NO

做法与思路

事实上这道题我一开始没注意到数量级,是用dfs做的,印象里只过了四个点…
然而这道题本质是考察贪心思想。
我们将两个购买方式分别定为策略一和策略二,如果咕咕咚在第i天使用了两次策略二,那么本质上与第i天使用策略一,第i+1天再使用策略一是没有区别的。所以我们可以尽可能的在前一天使用策略一,不足2时再使用策略二凑齐,这就形成了贪心策略。在运行过程中如果出现了某天的个数变成了负数或者是到了最后一天剩余奇数个则输出NO。

代码

#include <iostream>
using namespace std; 
int a[100001];
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	int day;
	cin>>day;
	for(int i=1;i<=day;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=day;i++)
	{	
		if((i==day)&&(a[i]%2==1)) 
		{
			cout<<"NO";
			return 0;
		}
		if(a[i]<0) 
		{
			cout<<"NO";
			return 0;
		}
		a[i+1]-=a[i]%2;
	}
	cout<<"YES";
	return 0;
}

题目三

题目描述

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

input

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

output

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

example

input 1

4
4 2 2 3
12

output 1

39
1

做法与思路

我是用广搜来解决这道题目的,不过这道题目本身的重点应该不是广搜。而是过程中如何选择合适的结构体存储射线以及如何剪枝。
关于射线,我们需要它的起始点坐标,分裂的方向以及它是第几次分裂。注意方向可以用数字记录,0代表正上方,1代表右上,以此类推,存储方便而且+1-1即可描述状态变化.
关于剪枝,由数据量我们可以意识到后期的分裂是极为密集的,所以对本次分裂中到达的同向终点我们要只记录一次,不然队列内会有极多重复数据,导致stl或者tle。坐标相同,方向相同,分裂次数相同,则这两个终点(下次分裂的起点)就是等价的。可以直接开一个4维judge数组进行标记。

代码

#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
int n[31];
int numble;
bool j[500][500]={false};
bool j2[500][500][8][32]={false};//x,y,v,分裂次数 
bool judge=0;
int sum;
int d[]={0,1,1,1,0,-1,-1,-1};
int b[]={1,1,0,-1,-1,-1,0,1}; 
struct shexian{
	int x,y;//起始点的坐标
	int v;//指示方向
	int s;//分裂次数 
	shexian()
	{
		x=0;y=0;v=0;s=0;
	} 
	shexian(int tx,int ty,int tv,int ts)
	{
		x=tx;y=ty;v=tv;s=ts;
	}
};	
queue<shexian> t;

int main(int argc, char** argv) {
	cin>>numble;
	for(int i=0;i<numble;i++)	cin>>n[i];
	t.push(shexian(250,250,0,0));
	while(!t.empty())
	{
		judge=1;
		shexian tem=t.front();
		int x=tem.x,y=tem.y,i=tem.s+1;
		for(int m=0;m<n[tem.s];m++)
		{		
			x=x+d[tem.v];
			y=y+b[tem.v];
			if(!j[x][y])
			{
				j[x][y]=1;
				sum++;
			}
		}
		if(i<numble)
		{
			if(j2[x][y][tem.v][tem.s]==0)
			{ 
				j2[x][y][tem.v][tem.s]=1;
				t.push(shexian(x,y,(tem.v+1)%8,i));
				t.push(shexian(x,y,(tem.v+7)%8,i));
			}
		}
		t.pop();
	}
	cout<<sum<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值