备战蓝桥杯 Day3

搜索与回溯

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
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
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
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
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
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
#include
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
#include
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
#include
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;
}

 

你可能感兴趣的:(insist,蓝桥杯,算法,深度优先)