Summer Online Training Camp 1 for ICPC Training League (Recursion & Backtracking)

题目链接:https://vjudge.net/contest/383777

The time we spent together is the happiest time since I went to college.

It is apparent that you not only give me a considerable number of happiness but also teach me a lot.

This article is dedicated to you.

I wish you all the best.

A - 放苹果

题解链接:https://blog.csdn.net/weixin_43772166/article/details/107406580

使用dfs枚举每次拿的个数,当前拿的个数要大于等于前一次拿的个数

#include <bits/stdc++.h>
using namespace std;

int res;
// u 表示当前至少要拿的个数,state 为剩余苹果数
void dfs(int u, int state, int cnt)
{
	if (cnt == 1) {
		res++;
		return;
	}
	for (int i = u; i <= state / cnt; i++) {
		dfs(i, state - i, cnt - 1);
	}
}

int main(void)
{
	int t, m, n;
	cin >> t;
	while (t--) {
		res = 0;
		cin >> m >> n;
		dfs(0, m, n);
		cout << res << endl;
	}
	
	return 0;
}

B - Symmetric Order

当 i%2==0 时输出,否则压入栈,最后依次输出栈内所有元素即可

#include <iostream>
#include <stack>
#include <string>
using namespace std;

stack<string> stk;

int main(void)
{
	int n, idx = 1;
	string s;
	while (cin >> n && n) {
		cout << "SET " << idx++ << endl;
		for (int i = 0; i < n; i++) {
			cin >> s;
			if (i % 2 == 0) {
				cout << s << endl;
			} else {
				stk.push(s);
			}
		}
		while (stk.size()) {
			s = stk.top(); stk.pop();
			cout << s << endl;
		}
	}
	
	return 0;
}

C - Fractal Streets

题解链接:https://blog.csdn.net/qq_33957603/article/details/80456975

yfy同学的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long LL;

void calc(int n,LL id,LL &x,LL &y)
{
	if(n==1)
	{
		if(id==1)
			x=1;y=1;
		if(id==2)
			x=1,y=2;
		if(id==3)
			x=2,y=2;
		if(id==4)
			x=2,y=1;
	}
	else
	{
		LL _id=(1<<(n-1))*(1<<(n-1));
		if(id<=_id)
			calc(n-1,id,y,x);
		else if(id<=2*_id)
		{
			calc(n-1,id-_id,x,y);
	    	y+=1<<(n-1);
		}
		else if(id<=3*_id)
		{
			calc(n-1,id-2*_id,x,y);
		    x+=1<<(n-1);
		    y+=1<<(n-1);
		}
		else
		{
			calc(n-1, id-3*_id, y,x);
			x=(1<<n)+1-x;
			y=(1<<n-1)+1-y;
		}

	}
}


int main()
{
	int _w;
	scanf("%lld",&_w);
	while(_w--)
	{
	    int n;
	    LL h,o;
	    LL x1,y1,x2,y2;
	    cin>>n>>h>>o;
    	calc(n,h,x1,y1);
	    calc(n,o,x2,y2);
	    double sq = (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
	    printf("%.0lf\n",sqrt(sq)*10);
	}
	return 0;
}

D - Fractal

受到yfy同学的启发后写出来的
使用dfs递归求解图形,预处理出所有小于等于7的情况

#include <iostream>
#include <cmath>
using namespace std;
const int N = 1005; 

bool G[N][N];

void dfs(int x, int y, int n)
{
	if (n == 1) {
		G[x][y] = 1;
		return;
	}
	// 当前图形每个小部分的边长
	int len = pow(3.0, (double)n - 2);
	
	dfs(x, y, n - 1);
	dfs(x, y + 2*len, n - 1);
	dfs(x + len, y + len, n - 1);
	dfs(x + 2*len, y, n - 1);
	dfs(x + 2*len, y + 2*len, n - 1);
}

int main(void)
{
	// 预处理 
	dfs(0, 0, 7);
	
	int n;
	while (cin >> n && n != -1) {
		// 图形的边长 
		int len = pow(3.0, (double)n - 1);
		for (int i = 0; i < len; i++) {
			for (int j = 0; j < len; j++) {
				if (G[i][j]) 
					cout << 'X';
				else
					cout << ' ';
			}
			cout << endl;
		}
		cout << "-" << endl;
	}
	
	return 0;
}

E - Red and Black

从人的位置开始深搜,看能够到达多少个地方

#include <iostream>
using namespace std;

int m, n, ans;
char ma[25][25];
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};

void dfs(int x, int y)
{
	ans++;
	ma[x][y] = '#';
	for (int i = 0; i < 4; i++){
		int nx = x + dx[i]int ny = y + dy[i];
		if (nx >= 0 && nx < m && ny >= 0 && ny < n && ma[nx][ny] == '.')
			dfs(nx, ny);
	}
}

int main(void)
{
	while (cin >> n >> m){
		ans = 0;
		if (m == 0 && n == 0)
			break;
		for (int i = 0; i < m; i++)
			cin >> ma[i];
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				if (ma[i][j] == '@')
					dfs(i, j);
		cout << ans << endl;
	}
	return 0;
}

F - The Sultan’s Successors

The Sultan of Nubia has no children, so she has decided that the country will be split into up tokseparate parts on her death and each part will be inherited by whoever performs best at some test. Itis possible for any individual to inherit more than one or indeed all of the portions. To ensure thatonly highly intelligent people eventually become her successors, the Sultan has devised an ingenioustest. In a large hall filled with the splash of fountains and the delicate scent of incense have beenplacedkchessboards. Each chessboard has numbers in the range 1 to 99 written on each square and issupplied with 8 jewelled chess queens. The task facing each potential successor is to place the 8 queenson the chess board in such a way that no queen threatens another one, and so that the numbers onthe squares thus selected sum to a number at least as high as one already chosen by the Sultan. (Forthose unfamiliar with the rules of chess, this implies that each row and column of the board containsexactly one queen, and each diagonal contains no more than one.)

Write a program that will read in the number and details of the chessboards and determine thehighest scores possible for each board under these conditions. (You know that the Sultan is both agood chess player and a good mathematician and you suspect that her score is the best attainable.)

Input

Input will consist ofk(the number of boards), on a line by itself, followed byksets of 64 numbers,each set consisting of eight lines of eight numbers. Each number will be a positive integer less than100. There will never be more than 20 boards.

Output

Output will consist ofknumbers consisting of yourkscores, each score on a line by itself and rightjustified in a field 5 characters wide.

Sample Input

1
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
48 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64

Sample Output

260

8皇后问题,枚举出所有的情况,求出最大得分

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
// 主对角线,副对角线,列 
bool a[30], b[30], c[30];
int n, res, ma[30][30];

void dfs(int x, int cnt) 
{
	if (x == 8) {
		res = max(res, cnt);
		return;
	}
	for (int j = 0; j < 8; j++) {
		// 当前位置可以放置皇后 
		if (!a[x - j + 8] && !b[x + j] && !c[j]) {
			a[x - j + 8] = b[x + j] = c[j] = 1;
			dfs(x + 1, cnt + ma[x][j]);
			a[x - j + 8] = b[x + j] = c[j] = 0;
		}
	}
	return;
}

int main(void)
{
	int k;
	scanf("%d", &k);
	for (int i = 0; i < k; i++) {
		for (int j = 0; j < 8; j++)
			for (int h = 0; h < 8; h++)
				scanf("%d", &ma[j][h]);
		memset(a, 0, sizeof a);
		memset(b, 0, sizeof b);
		memset(c, 0, sizeof c);
		res = 0;
		
		dfs(0, 0);
		printf("%5d\n", res);
	}
	
	return 0;
}

G - The Settlers of Catan

注意要保存边是否走过,而不要保存点是否走过。因为有环时保存点的话,会有一条边走不到。

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

bool G[30][30], vis[30][30];
int n, m, res;

void dfs(int u, int state)
{
	res = max(res, state);
	for (int i = 0; i < n; i++) {
		if (G[u][i] && vis[u][i] == 0) {
			vis[u][i] = vis[i][u] = 1;
			dfs(i, state + 1);
			vis[u][i] = vis[i][u] = 0;
		}
	}
}

int main(void)
{
	int u, v;
	while (cin >> n >> m && n && m) {
		memset(G, 0, sizeof G);
		res = 0;
		while (m--) {
			cin >> u >> v;
			G[u][v] = G[v][u] = 1;
		}
		
		for (int i = 0; i < n; i++) {
			dfs(i, 0);
		}
		cout << res << endl;
	}
	
	return 0;
}

H - Transportation

先对m个订单按开始站点从小到大进行排序,对订单进行dfs
如果接受当前站点的订单,就在数组中结束站点加上下车人数
每到一个新的站点时,剩余容量加上从刚才站点到当前站点的下车人数

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

int n, b, m, res;
struct pass{
	int st, ed, cost;
	bool operator < (const pass &b) const {
		return st < b.st;
	}
}a[25];

// 每个站点下车的人数 
int cnt[30];
// past表示刚才的站点,u表示当前站点 
void dfs(int past, int u, int vol, int state)
{
	for (int i = past + 1; i <= a[u].st; i++) 
		vol += cnt[i];
	past = a[u].st;
	
	// 处理完m个订单
	if (u == m) {
		res = max(res, state);
		return;
	}
	
	if (vol >= a[u].cost) {
		cnt[a[u].ed] += a[u].cost;
		dfs(past, u + 1, vol - a[u].cost, state + (a[u].ed - a[u].st) * a[u].cost);
		cnt[a[u].ed] -= a[u].cost;
	}
	dfs(past, u + 1, vol, state);
}

int main(void)
{
	while (cin >> n >> b >> m && n) {
		res = 0;
		memset(a, 0, sizeof a);
		memset(cnt, 0, sizeof cnt);
		
		for (int i = 0; i < m; i++)
			cin >> a[i].st >> a[i].ed >> a[i].cost;
		sort(a, a + m);
		 
		dfs(0, 0, n, 0);
		cout << res << endl;
	}
	return 0;	
}

I - Don’t Get Rooked

枚举16个位置,每个位置均有放或不放两种情况

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

int n, res;
char G[5][5];
bool vis[5][5];
// 判断当前位置能不能放 
bool judge(int x, int y)
{
	bool flag = 1;
	if (G[x][y] == 'X') 
		flag = 0;
	
	// 向上走 
	for (int dx = -1; dx >= -3; dx--) {
		int nx = x + dx, ny = y;
		if (nx >= 0 && nx < n) {
			if (G[nx][ny] == 'X')
				break;
			if (vis[nx][ny] == 1)
				flag = 0;
		}
	}
	
	// 向左走 
	for (int dy = -1; dy >= -3; dy--) {
		int nx = x, ny = y + dy;
		if (ny >= 0 && ny < n) {
			if (G[nx][ny] == 'X')
				break;
			if (vis[nx][ny] == 1)
				flag = 0;
		}
	}
	
	return flag;
}

void dfs(int x, int y, int state)
{
	res = max(res, state);
	// 当前行
	for (int j = y + 1; j < n; j++) {
		if (judge(x, j)) {
			vis[x][j] = 1;
			dfs(x, j, state + 1);
			vis[x][j] = 0;
		}
		// 不放 
		dfs(x, j, state);
	}
	// 后面的行
	for (int i = x + 1; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (judge(i, j)) {
				vis[i][j] = 1;
				dfs(i, j, state + 1);
				vis[i][j] = 0;
			}
			dfs(i, j, state);
		}
	}
}

int main(void)
{
	while (cin >> n && n) {
		res = 0;
		for (int i = 0; i < n; i++)
			cin >> G[i];
		// (0,0)放 
		if (G[0][0] == '.') {
			vis[0][0] = 1;
			dfs(0, 0, 1);
			vis[0][0] = 0;
		}
		
		// (0,0)不放
		dfs(0, 0, 0); 
		
		cout << res << endl;
	}
	
	return 0;
}

J - 8 Queens Chess Problem

被鬼畜的格式给搞晕了
和普通八皇后不同的是,本题是按列搜索的

#include <bits/stdc++.h>
using namespace std;
// 左对角线、右对角线、行
bool a[20], b[20], c[20];
// col 为预先放置的棋子的列 
int col, idx;
bool vis[10][10];

void dfs(int y)
{
	// 遍历完8列 
	if (y == 9) {
		cout << setw(2) << idx++ << "     ";
		for (int j = 1; j <= 8; j++)
			for (int i = 1; i <= 8; i++)
				if (vis[i][j] == 1)
					cout << " " << i;
		cout << endl;
		return;
	}
	// 该列已经被放置了 
	if (y == col) {
		dfs(y + 1);
	} else {
		// 遍历该列有哪些位置可以放 
		for (int i = 1; i <= 8; i++) {
			int ld = i - y + 8, rd = i + y;
			if (!a[ld] && !b[rd] && !c[i]) {
				a[ld] = b[rd] = c[i] = vis[i][y] = 1;
				dfs(y + 1);
				a[ld] = b[rd] = c[i] = vis[i][y] = 0;
			}
		}
	}
}

int main(void)
{
	int t, sx, sy;
	cin >> t;
	while (t--) {
		idx = 1;
		
		for (int i = 0; i < 20; i++)
			a[i] = b[i] = c[i] = 0;
		memset(vis, 0, sizeof vis);
		
		cin >> sx >> sy;
		a[sx - sy + 8] = b[sx + sy] = c[sx] = 1;
		col = sy;
		vis[sx][sy] = 1;
		
		cout << "SOLN       COLUMN" << endl;
		cout << " #      1 2 3 4 5 6 7 8" << endl;
		cout << endl;
		
		dfs(1);
		if (t > 0) cout << endl;
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43772166/article/details/107416107
今日推荐