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

T1 瑞神的序列

题目描述:

瑞神的数学一向是最好的,连强大的咕咕东都要拜倒在瑞神的数学水平之下,虽然咕咕东很苦恼,但是咕咕东拿瑞神一点办法都没有。 5.1期间大家都出去玩了,只有瑞神还在孜孜不倦的学习,瑞神想到了一个序列,这个序列长度为 n,也就是一共有 n个数,瑞神给自己出了一个问题:数列有几段? 段的定义是连续的相同的最长整数序列。
输入描述:

输入第一行一个整数n,表示数的个数。
接下来一行n个空格隔开的整数,表示不同的数字。
输出描述:

输出一行,这个序列有多少段 。
样例输入:

12
2 3 3 6 6 6 1 1 4 5 1 4

1
2

样例输出:

8
思路:创建数组a[n]储存此序列,p储存段数,从序列第二位开始,如果此位置的值不等于上个位置的值,p加一,最后输出p。

#include <iostream>
#include <algorithm>
using namespace std;
int n,a[10000],p;

int main(){
	cin>>n;
	p=1;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(i!=1){
			if(a[i]!=a[i-1]) p++;
		}
	}
	cout<<p;
	return 0;
} 

T2 消消乐大师——Q老师

题目描述:

Q老师是个很老实的老师,最近在积极准备考研。Q老师平时只喜欢用Linux系统,所以Q老师的电 脑上没什么娱乐的游戏,所以Q老师平时除了玩Linux上的赛车游戏SuperTuxKart之外,就是喜欢消消乐了。 游戏在一个包含有 n 行 m 列的棋盘上进行,棋盘的每个格子都有一种颜色的棋子。当一行或一列 上有连续三个或更多的相同颜色的棋子时,这些棋子都被消除。当有多处可以被消除时,这些地方的棋子将同时被消除。 一个棋子可能在某一行和某一列同时被消除。 由于这个游戏是闯关制,而且有时间限制,当Q老师打开下一关时,Q老师的好哥们叫Q老师去爬泰山去了,Q老师不想输在这一关,所以它来求助你了!!
输入描述:

输入第一行包含两个整数n,m,表示行数和列数 ,接下来n行m列,每行中数字用空格隔开,每个数字代表这个位置的棋子的颜色。数字都大于0。
输出描述:

输出n行m列,每行中数字用空格隔开,输出消除之后的棋盘。(如果一个方格中的棋子被消除, 则对应的方格输出0,否则输出棋子的颜色编号。)
样例输入1

4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4

1
2
3
4
5

样例输出1

2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4

1
2
3
4

样例输入2

4 5
2 2 3 1 2
3 1 1 1 1
2 3 2 1 3
2 2 3 3 3

1
2
3
4
5

样例输出2

2 2 3 0 2
3 0 0 0 0
2 3 2 0 3
2 2 0 0 0
思路:
建立一个set集合,遍历每一个点,检查这个点的x轴和y轴方向,若在某方向上满足消除的条件,则将这个方向上的对应点放入set中。最后遍历set,将对应点的值改为0即可。
改进:建立两个二维数组分别表示某个点的x或y轴方向是否已经检查,若没有则检查,若已经检查则跳过。

#include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
struct pos {
	int x, y;
	bool operator<(const pos& s) const
	{
		return x != s.x ? x < s.x : y < s.y;
	}
};
int n, m, a[35][35];
vector<pos> x;
vector<pos> y;
queue<pos> g;
queue<pos> xx;
queue<pos> yy;
set<pos> c;
void chushi() {
	x.clear();
	y.clear();
}
void change(int i, int l) {
	x.push_back({ i,l });
	y.push_back({ i,l });
	xx.push({ i,l });
	yy.push({ i,l });
	while (!xx.empty()) {
		pos t = xx.front();
		xx.pop();
		pos u;
		u.y =  t.y;
		u.x = t.x + 1;
		if (u.x <= n && a[u.x][u.y] == a[t.x][t.y]) xx.push(u), x.push_back(u);
	}
	xx.push({ i,l });
	while (!xx.empty()) {
		pos t = xx.front();
		xx.pop();
		pos u;
		u.y = t.y;
		u.x = t.x - 1;
		if (u.x>=1 && a[u.x][u.y] == a[t.x][t.y]) xx.push(u), x.push_back(u);
	}
	if (x.size() >= 3) {
		for (unsigned k = 0; k < x.size(); k++) {
			c.insert(x[k]);
		}
	}
	while (!yy.empty()) {
		pos t = yy.front();
		yy.pop();
		pos u;
		u.x = t.x;
		u.y = t.y + 1;
		if (u.y <= m && a[u.x][u.y] == a[t.x][t.y]) yy.push(u), y.push_back(u);
	}
	yy.push({ i,l });
	while (!yy.empty()) {
		pos t = yy.front();
		yy.pop();
		pos u;
		u.x = t.x;
		u.y = t.y -1;
		if (u.y >=1 && a[u.x][u.y] == a[t.x][t.y]) yy.push(u), y.push_back(u);
	}
	if (y.size() >= 3) {
		for (unsigned k = 0; k < y.size(); k++) {
			c.insert(y[k]);
		}
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int l = 1; l <= m; l++) {
			cin >> a[i][l];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int l = 1; l <= m; l++) {
			chushi();
			change(i, l);
		}
	}
	for (auto it = c.begin(); it != c.end(); it++) {
		a[it->x][it->y] = 0;
	}
	for (int i = 1; i <= n; i++) {
		if (i > 1) cout << endl;
		cout<<a[i][1];
		for (int l = 2; l <= m; l++) {
			cout << " " << a[i][l];
		}
	}
	return 0;
}

T4 咕咕东学英语

题目描述:

咕咕东很聪明,但他最近不幸被来自宇宙的宇宙射线击中,遭到了降智打击,他的英语水平被归 零了!这一切的始作俑者宇宙狗却毫不知情! 此时咕咕东碰到了一个好心人——TT,TT在吸猫之余教咕咕东学英语。今天TT打算教咕咕东字母A 和字母B,TT给了咕咕东一个只有大写A、B组成的序列,让咕咕东分辨这些字母。 但是咕咕东的其他学科水平都还在,敏锐的咕咕东想出一个问题考考TT:咕咕东问TT这个字符串 有多少个子串是Delicious的。 TT虽然会做这个问题,但是他吸完猫发现辉夜大小姐更新了,不想回答这个问题,并抛给了你, 你能帮他解决这个问题吗?
Delicious定义:对于一个字符串,我们认为它是Delicious的当且仅当它的每一个字符都属于一个大于1的回文子串中。
输入描述:

输入第一行一个正整数n,表示字符串长度, 接下来一行,一个长度为n,只由大写字母A、B构成的字符串。
输出描述:

输出仅一行,表示符合题目要求的子串的个数。
样例输入:

5
AABBB

1
2

样例输出:

6

1

样例解释:

对于该样例,符合条件的六个子串分别是:
s1-s4 AABB
s1-s5 AABBB
s3-s4 BB
s3-s5 BBB
s4-s5 BB
思路:首先确定对于长度为n的字符串一共有(n-1)*n/2中可能,当减去所有不满足条件的情况即为答案。
经过观察可知,不满足Delicious定义的字符串为…AB…或者…BA…这样的字符串,对于[n]AB这样的字符串,一共有n种不满足条件的子串.为AB,AAB,…,[n]AB,若最左边的A之前还有B,则形成BA[n],又有n个不满足条件的子串,说明此时一段要计算两次,而左右两端只用计算一次。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
const int ma=3E5+10;
string s;
long long a[ma],len,num;
int main(){
	cin>>len;
	cin>>s;
	fill(a,a+ma,0);
	long long p=0;
	a[0]=1;
	num=len*(len-1)/2;
	for(unsigned i=1;i<s.size();i++){
		if(s[i]==s[i-1]) a[p]++;
		else {
			p++;
			a[p]++;
		}
	}
	if(p==0){
	    cout<<num;
		return 0;
	}
	num-=a[0];
	for(int i=1;i<p;i++) num-=2*a[i];
	num-=a[p];
	num+=p;
	cout<<num;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值