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

Ruratania is just entering capitalism and is establishing new enterprising activities in many fields in- cluding transport. The transportation company TransRuratania is starting a new express train from city A to city B with several stops in the stations on the way. The stations are successively numbered, city A station has number 0, city B station number m. The company runs an experiment in order to improve passenger transportation capacity and thus to increase its earnings. The train has a maximum capacity n passengers. The price of the train ticket is equal to the number of stops (stations) between the starting station and the destination station (including the destination station). Before the train starts its route from the city A, ticket orders are collected from all onroute stations. The ticket order from the station S means all reservations of tickets from S to a fixed destination station. In case the company cannot accept all orders because of the passenger capacity limitations, its rejection policy is that it either completely accept or completely reject single orders from single stations.

Write a program which for the given list of orders from single stations on the way from A to B determines the biggest possible total earning of the TransRuratania company. The earning from one accepted order is the product of the number of passengers included in the order and the price of their train tickets. The total earning is the sum of the earnings from all accepted orders.

Input

The input file is divided into blocks. The first line in each block contains three integers: passenger capacity n of the train, the number of the city B station and the number of ticket orders from all stations. The next lines contain the ticket orders. Each ticket order consists of three integers: starting station, destination station, number of passengers. In one block there can be maximum 22 orders. The number of the city B station will be at most 7. The block where all three numbers in the first line are equal to zero denotes the end of the input file.

Output

The output file consists of lines corresponding to the blocks of the input file except the terminating block. Each such line contains the biggest possible total earning.

Sample Input

10 3 4
0 2 1
1 3 5
1 2 7
2 3 10
10 5 4
3 5 10
2 4 9
0 2 5
2 5 8
0 0 0

Sample Output

19
34

让我极其崩溃的一道题 QAQ

先对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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值