程序设计思维与实践 CSP-M1 补题 (3/4/数据班)

咕咕东的奇遇

题目描述

咕咕东是个贪玩的孩子,有一天,他从上古遗迹中得到了一个神奇的圆环。这个圆环由字母表组成首尾相接的环,环上有一个指针,最初指向字母a。咕咕东每次可以顺时针或者逆时针旋转一格。例如,a顺时针旋转到z,逆时针旋转到b。咕咕东手里有一个字符串,但是他太笨了,所以他来请求你的帮助,问最少需要转多少次。
加个示意图
输入格式

输入只有一行,是一个字符串。
输出格式
输出最少要转的次数。

思路:创建一个双向环形链表类,实现函数count(node* first, char aim)表示从位置first开始向两边转动到aim的最少转动次数。对于字符串第一个字符,first从‘a’开始,接下来对于每一个字符,从上一个位置的字符开始找到aim,统计总共转动的次数即可。

#include <iostream>
#include <string>
using namespace std;
struct node {
	char x='1';
	node* next = NULL;
	node* pre = NULL;
	node(){}
};
class zimu {
public:
	zimu() {
		head = new node();
		last = new node();
		head->x = 'a';
		last->x = 'b';
		head->pre = last;
		last->next = head;
		head->next = last;
		last->pre = head;
		first = head;
		num = 0;
	}
	void count(node* first, char aim);
	void insert(char x);
	node* head;
	node* last;
	node* first;
	int num;

};
void zimu::insert(char x) {
	node* p;
	p = new node();
	p->x = x;
	this->last->next = p;
	p->pre = this->last;
	this->last = p;
	this->last->next = this->head;
	this->head->pre = this->last;

}
void zimu::count(node* first, char aim) {
	node* a = first;
	node* b = first;
	node* q=NULL;
	int n = 0;
	while (a->x != aim && b->x != aim) {
		a = a->next;
		b = b->pre;
		n++;
	}
	if (a->x == aim) q = a;
	else if (b->x == aim) q = b;
	this->num = this->num + n;
	this->first = q;
}
int main() {
	zimu t;
	int i,n=0;
	for (i = 2; i <= 25; i++) {
		t.insert(t.head->x + i);
	}
	string s;
	cin >> s;
	while (n != s.size()) {
		t.count(t.first, s[n]);
		n++;
	}
	cout << t.num;
	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
思路:首先统计他n天总共要买的数量,若为奇数则输出“NO”,因为不管是一次买两个或者买一个送一张券都相当于买了偶数个,所以最后总共买的数量一定是偶数。
若购买总数为偶数,设置一个变量为s表示剩余的券的数量,初始化为0,对于每一天需要购买的数量,与s进行比较,若购买数量小于s,则表示当天买的数量不能满足要求。之后更新s=(day[i]-s)%2;可以设置一个逻辑变量判断是否可以满足要求。

#include <iostream>
using namespace std;

int main(){
	int day[200000],i,x,sum=0,s=0;
	cin>>x;
	for(i=0;i<x;i++){
		cin>>day[i];
		sum=sum+day[i];
	}
	bool lo=true;
	if(sum%2!=0){
		cout<<"NO";
		return 0;
	}
	for(i=0;i<x;i++){
		if(day[i]-s<0){
			lo=false;
			break;
		}
		s=(day[i]-s)%2;
	}
	if(lo) cout<<"YES";
	else if(!lo) cout<<"NO";
	return 0;
} 

可怕的宇宙射线

题目描述

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

输入第一行包含一个正整数 ,表示宇宙射线会分裂 次 第二行包含n个正整数 ,第 个数 表示第 次分裂的宇宙射线会在它原方向上继续走多少个单位长度。
输出描述

输出一个数 ,表示有多少个位置会被降智打击
思路:创建两个数组x_way[] = { 0,1,1,1,0,-1,-1,-1 };
y_way[] = { 1,1,0,-1,-1,-1,0,1 }表示对于每一个点可以移动的八个位置。对于每一个顶点,它的分裂遵循以下规律:
在这里插入图片描述每个顶点的分裂方向为当前方向way:(way + 7) % 8和 (way + 1) % 8;
再创建一个数组判断此点是否经过过,采用广度优先搜索方法,此题解决。

#include <iostream>
#include <stdio.h>
#include <cmath>
#include <set>
using namespace std;

struct node {
	int x;
	int y;
	int way;
	bool operator<(const node& s) const
	{
		if (x != s.x) return x < s.x;
		else if (y != s.y) return y < s.y;
		else if (way != s.way) return way < s.way;
		else return false;
	}
};
int x_way[] = { 0,1,1,1,0,-1,-1,-1 };
int y_way[] = { 1,1,0,-1,-1,-1,0,1 };
set<node> v1, v2;
int gg[800][800] = { 0 };
int main() {

	int n, num = 1;
	cin >> n;
	int a[100] = { 0 };
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	node first;
	first.x = 300;
	first.y = 300;
	first.way = 0;
	gg[first.x][first.y] = 1;
	v1.insert(first);
	for (int i = 0; i < n; i++) {
		for (auto it = v1.begin(); it != v1.end(); it++) {
			node ll, r;
			int x = it->x, y = it->y, way = it->way;
			for (int l = 0; l < a[i] - 1; l++) {
				x = x + x_way[way];
				y = y + y_way[way];
				if (gg[x][y] == 0) {
					gg[x][y] = 1;
					num++;
				}
			}
			if (i == n - 1) continue;
			ll.way = (way + 7) % 8;
			r.way = (way + 1) % 8;
			ll.x = x + x_way[ll.way];
			ll.y = y + y_way[ll.way];
			r.x = x + x_way[r.way];
			r.y = y + y_way[r.way];
			if (gg[ll.x][ll.y] == 0) {
				gg[ll.x][ll.y] = 1;
				num++;
			}
			if (gg[r.x][r.y] == 0) {
				gg[r.x][r.y] = 1;
				num++;
			}
			v2.insert(ll);
			v2.insert(r);
		}
		v1 = v2;
		v2.clear();
	}

	cout <<num;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值