[Problem Solving Report] 2020 Blue Bridge Cup Group B simulation result of garlic passenger filling in the blanks: Apple

Problem Description

There are 3030 baskets, and each basket contains several apples. The sequence of the number of apples in the basket has been given.

Now we need to distribute the apples to the children. Each child will either take three apples from one basket or one apple from each of the three adjacent baskets.

Apple can remain, and different ways of holding will lead to different answers. For example, for the sequence 3 1 3, it can be divided into two children and become 0 1 0; it can also be divided into two children and become 2 0 2. At this time, it can no longer be divided. So the answer is 22.

For the following sequence, how many children can be shared at most?


As long as you want the most or the least, 95% are the ideas of wide search or deep search

There are many blogs on the Internet that use greedy solutions, which is not right at all. This question is greedy and can only produce examples. It is wrong to change the data with tricky points.

The correct idea is DFS. There are only two operations to take the number, either a single -3, or three adjacent -1s. Then, as long as you use deep search simulation and traverse each possibility, you can naturally find the minimum.


Note: If you simply use search to run, then each number has to take the adjacent two each minus one and take the number minus three operations, that is, you need to run 3 to the 30th power, for the computer It is still very slow, so it needs to be optimized with pruning.


Reference Code

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

int ans = 0; 
int a[117] = {
    
    7,2,12,5,9, 9,8,10,7,10, 5,4,5,8,4, 4,10,11,3,8, 7,8,3,2,1, 6,3,9,7,1};
int sum[117];

void dfs(int idex, int num) {
    
    
	if(idex == 30) {
    
    
		ans = max(ans, num);
		return;
	}
	if(sum[idex] / 3 + num < ans) return; 	//剪枝优化
	//不公用
	dfs(idex+1, num+a[idex]/3);
	//往后公用 
	if(idex+2 < 30) {
    
    
		int min_num = min(a[idex], a[idex + 1]);
		min_num = min(min_num, a[idex+2]);		//共用最多能分几个
		for(int k = 1; k <= min_num; k++) {
    
    
			for(int i = 0; i < 3; i++) a[idex+i] -= k;
			dfs(idex+1, num+a[idex]/3+k);
			for(int i = 0; i < 3; i++) a[idex+i] += k;
		} 
	} 
}

int main() {
    
    
    for(int i = 29; i >= 0; i--) sum[i] = sum[i + 1] + a[i];
    for(int i = 0; i < 30; i++) cout << sum[i] << ' ';
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}


The future can be expected

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_43899069/article/details/109098805