备战蓝桥杯 Day3

目录

搜索与回溯

1222:放苹果

1221:分成互质组

1218:取石子游戏

数组 

 1126:矩阵转置

1127:图像旋转

 1128:图像模糊处理

1120:同行列对角线的格

string 

2046:【例5.15】替换字母

 2047:【例5.16】过滤空格

2048:【例5.18】串排序

string版本

map版本 

2049:【例5.19】字符串判等

2050:【例5.20】字串包含

1839:【05NOIP提高组】谁拿了最多奖学金(用例只通过30%)

1839:【05NOIP提高组】谁拿了最多奖学金


搜索与回溯

1222:放苹果

【题目描述】

把M�个同样的苹果放在N�个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K�表示)5,1,11,5,1 是同一种分法。

【输入】

第一行是测试数据的数目t�(0≤t≤200≤�≤20)。以下每行均包含二个整数M�和N�,以空格分开。1≤M,N≤101≤�,�≤10。

【输出】

对输入的每组数据M�和N�,用一行输出相应的K。

【输入样例】

1
7 3

【输出样例】

8
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int t, n, m;
int cnt[N];
int ans = 0;
//搜索状态为s,  s代表当前已经搜索的答案的累加和
void dfs(int s, int depth) {
	//5.终止条件
	if (s > n) return;
	if (depth <= m + 1 && s == n) {//n选r问题更改条件处
		ans++;
		return;
	}
	//1.枚举方案(枚举的时候直接排列变组合)
	for (int i = cnt[depth - 1]; i <= n; i++) {
		//2.本题需要重复搜索,则不需要加标记,故第二步略
		//3.搜索
		cnt[depth] = i;
		dfs(s + i, depth + 1);
		//4.回溯,若s作为状态传入dfs,则回溯的时候,s自动还原
	}
}
int main() {
	cin >> t;
	while (t--) {
		cin >> n >> m;
		cnt[0] = 1;
		ans = 0;//多组数据,相关状态初始化
		dfs(0, 1);//初始状态
		cout << ans << endl;
	}
	return 0;
}

1221:分成互质组

【题目描述】

给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?

【输入】

第一行是一个正整数n。1 ≤ n ≤ 10。

第二行是n个不大于10000的正整数。

【输出】

一个正整数,即最少需要的组数。

【输入样例】

6
14 20 33 117 143 175

【输出样例】

3

 本题需掌握的知识点:
1.互质的两个数a,b满足gcd(a,b)=1
2.若a,b,c互质,则c与a*b互质,反之也成立

#include<iostream>
using namespace std;
const int N = 1e4 + 10;
int n, a[N];
int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= n; i++) {//清零的位置不需要考虑
		for (int j = i + 1; j <= n; j++) {
			if (a[i] != 0 && gcd(a[i], a[j]) == 1) {
				a[i] *= a[j];
				a[j] = 0;
			}
		}
	}
	int cnt = 0;
	for (int i = 1; i <= n; i++) if (a[i] != 0) cnt++;
	cout << cnt << endl;
	return 0;
}

1218:取石子游戏

【题目描述】

有两堆石子,两个人轮流去取。每次取的时候,只能从较多的那堆石子里取,并且取的数目必须是较少的那堆石子数目的整数倍,最后谁能够把一堆石子取空谁就算赢。

比如初始的时候两堆石子的数目是25和7。

25 7-->11 7-->4 7-->4 3-->1 3-->1 0
选手1取选手2取选手1取选手2取选手1取

最后选手1(先取的)获胜,在取的过程中选手2都只有唯一的一种取法。

给定初始时石子的数目,如果两个人都采取最优策略,请问先手能否获胜。

【输入】

输入包含多数数据。每组数据一行,包含两个正整数a和b,表示初始时石子的数目。

输入以两个0表示结束。

【输出】

如果先手胜,输出"win",否则输出"lose"。

【输入样例】

34 12
15 24
0 0

【输出样例】

win
lose

【提示】

假设石子数目为(a,b)且a >= b,如果[a/b] >= 2则先手必胜,如果[a/b]<2,那么先手只有唯一的一种取法。[a/b]表示a除以b取整后的值。

#include<iostream>
using namespace std;
//搜索状态为a,b代表两堆石子的数量
bool dfs(int a, int b) {
	if (a < b) swap(a, b);
	if (a % b == 0) return true;//某一方赢了
	//枚举b的倍数i,但是要保证i*b不超过a
	for (int i = a / b; i >= 1; i--) 
		//枚举所有取法,但凡能找到一种让对方输的情况,那么当前选手都会赢
		if (dfs(a - i * b, b) == false) return true;
	return false;//枚举所有取法,都没找到一种让对方输的情况,那么当前选手输
}
//选手1执行dfs(7,3)=true    dfs(1,3)=true   dfs(4,3)=false    
//选手2执行dfs(4,3)=false   dfs(1,3)=true
//选手1执行dfs(1,3)赢了
//选手2执行dfs(1,3)赢了
int main() {
	int a, b;
	while (cin >> a >> b && a && b) {
		if (dfs(a, b) == true) cout << "win" << endl;
		else cout << "lose" << endl;
	}
	return 0;
}

数组 

 信息学奥赛一本通(C++版)在线评测系统

 1126:矩阵转置

#include<iostream>
using namespace std;
const int N = 1e2 + 10;
int a[N][N];
int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> a[i][j];
	for (int i = 1; i <= m; i++)
	{
		for (int j = 1; j <= n; j++)
			cout << a[j][i] << " ";
		cout << endl;
	}
	return 0;
}

1127:图像旋转

#include<iostream>
using namespace std;
const int N = 1e2 + 10;
int a[N][N];
int n, m;
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            cin >> a[i][j];
    for (int j = 1; j <= m; ++j)//遍历矩阵b,m行n列
    {
        for (int i = n; i >= 1; --i)
            cout << a[i][j] << ' ';
        cout << endl;
    }
	return 0;
}

 1128:图像模糊处理

#include<iostream>
#include<cmath>
using namespace std;
const int N = 1e2 + 10;
int a[N][N],b[N][N];
int n, m;
int s;//上下左右以及该点的平均值
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			cin >> a[i][j];
	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= m; ++j)
		{
			if (!(i == 1 || i == n || j == 1 || j == m))
			{
				s = a[i][j] + a[i - 1][j] + a[i + 1][j] + a[i][j - 1] + a[i][j + 1];
				s = round((double)s / 5);
				b[i][j] = s;
			}
			else
				b[i][j] = a[i][j];
		}
	}
	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= m; ++j)
			cout << b[i][j] << " ";
		cout << endl;
	}
	return 0;
}

1120:同行列对角线的格

#include<iostream>
#include<cmath>
using namespace std;
const int N = 1e2 + 10;
int a[N][N],b[N][N];
int n, x,y;
int main()
{
	cin >> n >> x>>y;
	for (int j = 1; j <= n; ++j)
		printf("(%d,%d) ", x, j);
	putchar('\n');
	for (int i = 1; i <= n; ++i)
		printf("(%d,%d) ", i, y);
	putchar('\n');
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			if (i - j == x - y)
				printf("(%d,%d) ", i, j);
	putchar('\n');
	for (int i = n; i >= 1; --i)
		for (int j = 1; j <= n; ++j)
			if (i + j == x + y)
				printf("(%d,%d) ", i, j);
	putchar('\n');
	return 0;
}

string 

2046:【例5.15】替换字母

#include<iostream>
#include<string>
using namespace std;
string s;
char a, b;
int main()
{
	getline(cin, s);
	cin >>a>>b;
	for (auto &c : s)
		if (c == a)
			c =b;
	cout << s;
	return 0;
}

2047:【例5.16】过滤空格

#include<iostream>
#include<string>
using namespace std;
string s;
char a, b;
int main()
{
	getline(cin, s);
	cin >>a>>b;
	for (auto &c : s)
		if (c == a)
			c =b;
	cout << s;
	return 0;
}

 2047:【例5.16】过滤空格

#include<iostream>
#include<string>
using namespace std;
string s;
int main()
{
	while(cin>>s)
	cout << s<<" ";
	return 0;
}

2048:【例5.18】串排序

string版本
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
string s;
int main()
{
	int n; cin >> n;
	string s[25];
	for (int i = 1; i <= n; i++)
	{
		cin >> s[i];
	}
	sort(s + 1, s + 1 + n);
	for (int i = 1; i <= n;i++) {
		cout << s[i] << endl;
	}
	return 0;
}
map版本 
#include<iostream>
#include<string>
#include<map>
using namespace std;
string s;
int main()
{
	map<string, int>mp;
	int n; cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> s;
		mp.insert({ s,i });
	}
	for (auto it : mp) {
		cout << it.first << endl;
	}
	return 0;
}

2049:【例5.19】字符串判等

#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
string s;
int main()
{
	string s1, s2,ss1,ss2;
	getline(cin, s1);
	getline(cin, s2);
	/*将大写字母全部转换成小写*/
	for (auto& c : s1)
		if (c >= 'A' && c <= 'Z')
			c += 32;
	for (auto& c : s2)
		if (c >= 'A' && c <= 'Z')
			c += 32;
	/*将去除空格的字符串复制到新变量*/
	for (auto& c : s1)
		if (c != ' ')
			ss1 += c;
	for (auto& c : s2)
		if (c != ' ')
			ss2 += c;
	/*字符串判等*/
	if (ss1 == ss2)
		cout << "YES";
	else
		cout << "NO";
	return 0;
}

2050:【例5.20】字串包含

#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
int main()
{
	string s1, s2;
	cin >> s1 >> s2;
	/*判断s1和s2谁的长度长*/
	if (s1.length() < s2.length())
		swap(s1, s2);
	s1 += s1;
	if (s1.find(s2) != -1)
		cout << "true";
	else
		cout << "false";
	return 0;
}

1839:【05NOIP提高组】谁拿了最多奖学金(用例只通过30%)

#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
const int N = 1e2 + 10;
struct stu {
    string name;
    int qmscore;
    int bjscore;
    char gb;
    char sf;
    int lw;
    int sum;
} s[N];

bool cmp(stu a, stu b) {
    if (a.sum == b.sum)
        return false;
    else
        return a.sum > b.sum;
}

int main() {
    int n; 
    cin >> n;
    for(int i=0; i < n; i++) {
        cin >> s[i].name >> s[i].qmscore >> s[i].bjscore >> s[i].gb >> s[i].sf >> s[i].lw;
        s[i].sum = 0;
        if (s[i].qmscore > 80 && s[i].lw >= 1) s[i].sum += 8000;
        if (s[i].qmscore > 85 && s[i].bjscore > 80) s[i].sum += 4000;
        if (s[i].qmscore > 90) s[i].sum += 2000;
        if (s[i].qmscore > 85 && s[i].sf == 'Y') s[i].sum += 1000;
        if (s[i].qmscore > 80 && s[i].gb == 'Y') s[i].sum += 850;
    }

    sort(s, s + n, cmp);

    int total_sum = 0;
    for (int i = 0; i < n; i++) {
        total_sum += s[i].sum;
    }

    cout << s[0].name << endl << s[0].sum << endl << total_sum;

    return 0;
}

1839:【05NOIP提高组】谁拿了最多奖学金

#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
const int N = 1e2 + 10;
string s;
int cnt;//统计数字个数
int main()
{
	getline(cin, s);
	//c++11特性
	for (auto c : s)
		if (c >= '0' && c <= '9')
			cnt++;
	cout << cnt;
	return 0;
}

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了一li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值