csp模测

A题 咕咕咚的奇遇

- 题意:
有一个由26个字母组成的圈,如下图所示
在这里插入图片描述
设起始位置为 ‘a’ ,从该字母圈中取出一个字符串(即轮流取出每个字符),求最小的步数是多少。
输入要求:
输入一行,为一个字符串
输出要求:
输出需要的最小步数
sample input:

hzet

sample output:

31

思路:
每次从所在的位置location,到目的位置 a[i],需要的步数为 abs(location - a[i]) 或 26 - abs(location - a[i]),对每个字母进行判断即可得到最小步数。
代码:

#include <iostream>
#include <math.h>
using namespace std;

char str[10000];

int main(){
	cin>>str;
	int i=0;
	char current='a';
	int step=0;
	while(str[i]!='\0'){
		if(abs(str[i]-current)<=13){
			step=step+abs(str[i]-current);
		} 
		else{
			step=step+26-abs(str[i]-current);
		}
		current=str[i];
		i++;
	}
	cout<<step<<endl;
}

B题:咕咕咚想吃饭

题意:
咕咕咚需要买生煎 n 天,每天需要 a[i] 个生煎,生煎店出售方式为:一次卖两个,或者一次卖一个加一张券(仅第二天可用),要求:判断出咕咕咚是否能每天都吃到需要的生煎,并且没有浪费的生煎或券。
输入要求:
第一行输入天数n,第二行输入 n 个数,分别对应第 i 天需要吃的生煎。
输出要求:
根据是否能每天吃到所需生煎且无浪费,输出“YES”或者“NO”。
sample input:

4
1 2 1 2

sample output:

YES

思路:

  • 定义一个 bool 型变量 quan,用于判断当天是否有券。
  • 使用一个 while 循环,对每一天进行判断:
    1、当天有券且当天所需生煎为奇数个;
    2、当天有券且当天所需生煎为偶数个;
    3、当天无券且当天所需生煎为奇数个;
    4、当天无券且所需生煎为偶数个。

代码:

#include <iostream>
#include <algorithm>
#include <vector> 
using namespace std;

vector<int> a;

int main(){
	int n,a_;
	cin>>n;
	//int a[n];
	for(int i=0;i<n;i++){
		cin>>a_;
		a.push_back(a_);
	}
	bool quan=false;//开始没有券 
	int date=0;
	while(date<n){
		if(quan==true){//当天有券 
			if(a[date]%2==1){//当天奇数个,而且有券 
			//把券用了
			quan=false; 
			}
			if(a[date]%2==0){
				if(a[date]==0){//不吃,但是有券 
					cout<<"NO"<<endl;
					return 0;
				}
				quan=true;
				if(date==n-1){//最后一天还有券 
					cout<<"NO"<<endl;
					return 0;
				}
			}
		} 
		else{//当天没有券 
			if(a[date]%2==1){//当天吃奇数个 
				quan=true;
				if(date==n-1){
					cout<<"NO"<<endl;
					return 0;
				}
			} 
			if(a[date]%2==0){
				quan=false;
			} 
		}
		date++;
	}
	cout<<"YES"<<endl;
}

C题 可怕的宇宙射线

题意:

宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),初始方向默认向上。宇宙射线会在发射出一段距离后分裂,向该方向的 左右45°方向分裂出两条宇宙射线。宇宙射线会分裂 n 次,每次分裂后会在分裂方向前进 a i a_i ai 个单位长度。
要求:计算在结束分裂后,有多少位置有宇宙射线。
输入要求:
输入第一行包含一个正整数 n,表示宇宙射线会分裂 n 次,第二行包含n个正整数,第 i 个数 表示第 i 次分裂的宇宙射线会在它原方向上继续走多少个单位长度。
输出要求:
输出一个 ans,表示有多少位置有宇宙射线。
sample input:

4
4 2 2 3

sample output:

39

射线分裂过程如下图所示:在这里插入图片描述

数据点说明:

  • 10%:n <= 10
  • 40%:n <= 20
  • 100%: n <= 30

思路:

  • 该题可以使用 bfs 或者 dfs,这里选择了 dfs,但是若直接使用 dfs,不进行剪枝,只能拿到 40 分,在 n <= 30
    的数据中会发生超时错误,所以需要进行对其进行适当的剪枝操作。
  • 若在同一个点,做方向相同,长度相等的分裂,则可以不再做此次分裂,即可减少大量操作。为了判断是否做过相同的分裂,定义一个 bool 类型四维数组 vis[300][300][31][8]。

代码:

#include <iostream>
#include <queue>
using namespace std;

struct point {
	int x, y;
	int num;//用来判断该点是第几次分裂到达的点 
	point() {}
	point(int x_, int y_, int _num = 0) {
		x = x_;
		y = y_;
		num = _num;
	}
};

int n;
//从向上开始顺时针的八种方向 
int dx[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
int dy[] = { 1, 1, 0, -1, -1, -1, 0, 1 };
int l[30];
int ans = 0;
queue<point> q;
bool vis[300][300][31][8];
bool reach[300][300];
//起点 (150,150) 

//dfs
void split(point p, int direction, int k) {
	if (vis[p.x][p.y][k][direction]) return;
	vis[p.x][p.y][k][direction] = true;
	for (int i = 0; i < l[k]; i++) {
		if (reach[p.x + dx[direction] * (i + 1)][p.y + dy[direction] * (i + 1)] == false) {
			reach[p.x + dx[direction] * (i + 1)][p.y + dy[direction] * (i + 1)] = true;
			ans++;
		}
	}
	point p_(p.x + dx[direction] * l[k], p.y + dy[direction] * l[k]);
	int direc1, direc2;
	switch (direction) {
		case 0: {
			direc1 = 7;
			direc2 = 1;
			break;
		}
		case 7: {
			direc1 = 6;
			direc2 = 0;
			break;
		}
		default: {
			direc1 = direction - 1;
			direc2 = direction + 1;
			break;
		}
	}
	
	if (k < n - 1) {
		split(p_, direc1, k + 1);
		split(p_, direc2, k + 1);
	}
	return;
}

int main() {
	cin >> n;
	//初始化
	for (int i = 0; i < n; i++) {
		cin >> l[i];
	}
	for (int i = 0; i < 300; i++) {
		for (int j = 0; j < 300; j++) {
			reach[i][j] = false;
			for (int k = 0; k < 31; k++) {
				for (int t = 0; t < 8; t++)
					vis[i][j][k][t] = false;
			}
		}
	}

	point p(150, 150);
	split(p, 0, 0);
	cout << ans << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值