NOI 1805: shredder DFS depth first search / map record answer / string to int

Posted by CoderGoblin on Wed, 09 Feb 2022 04:20:52 +0100

subject

Origin link

describe

You are now in charge of designing a new paper shredder. The general shredder cuts the paper into small pieces and becomes difficult to read. The new shredder you designed has the following characteristics:

1. Before each cutting, a target number of shredders should be given first, and a number should also be included on each piece of paper fed into the shredder.
2. Each piece of paper cut by the shredder includes a number.
3. It is required that the sum of the number on each piece of paper cut out should not be greater than the target number and closest to the target number.

For example, as shown in the figure below, suppose the target number is 50 and the number on the input paper is 12346. The shredder cuts the paper into 4 pieces, including 1, 2, 34 and 6 respectively. In this way, the sum of these numbers is 43 (= 1 + 2 + 34 + 6), which is the most close to 50 among all the segmentation methods. For another example, it is incorrect to divide into 1, 23, 4 and 6, because the sum is 34 (= 1 + 23 + 4 + 6), which is smaller than the result 43 just obtained. It is also incorrect to divide into 12, 34 and 6, because the sum is 52 (= 12 + 34 + 6), more than 50.

There are three special rules:
1. If the target number is the same as the number on the input paper, the paper will not be cut.
2. If the sum of the number of pieces of paper divided is greater than the target number no matter how it is cut, the printer displays an error message.
3. If there are many different cutting methods, the same optimal result can be obtained. Then the printer displays a denial of service message. For example, if the target number is 15 and the number on the input paper is 111, there are two different ways to get the optimal solution: cutting into 1 and 11 or cutting into 11 and 1. In this case, the printer will display a denial of service message.

In order to design such a shredder, you need to write a simple program to simulate the work of the printer. Given two numbers, the first is the target number, and the second is the number on the input paper. You need to give the paper shredder's segmentation method.
input
The input includes multiple groups of data, and each group includes a row. Each line includes two positive integers, representing the target number and the number on the input paper respectively. Known input guarantees that neither number will start with 0, and both numbers contain at most 6 numbers.

The last line of input includes two zeros, which indicates the end of input.
output
For each set of input data, output the corresponding output. There are three different output results:

sum part1 part2 ...
rejected
error

The first result indicates:
1. Each partj is a number on the cut paper. The order of partj is consistent with the order of numbers in the original number on the input paper.
2.sum is the sum of the numbers on the cut paper, that is: sum = part1 + part2 +
In the first result, two adjacent numbers are separated by a space.

If the sum of the number on the divided pieces of paper is greater than the target number no matter how it is cut, "error" is printed.
If there are many different cutting methods that can get the same optimal result, print "rejected".

sample input

50 12346
376 144139
927438 927438
18 3312
9 3142
25 1299
111 33333
103 862150
6 1104
0 0

sample output

43 1 2 34 6
283 144 139
927438 927438
18 3 3 12
error
21 1 2 9 9
rejected
103 86 2 15 0
rejected

analysis

DFS depth first search

void dfs(int total, int start, string& s, int n,string& cur)

total is the sum obtained in the previous step, s is the original string, that is, the note, start is the subscript in s at the beginning of the string to be processed, and cur stores the answer

void dfs(int total, int start, string& s, int n,string& cur){
	if(total > n){  //Boundary condition 1: total > N, which obviously does not meet the requirements
		return;
	}
	if(start == s.size()){ //Boundary condition 2: start has reached the end of the original string, that is, all the original strings have been enumerated 
		if(n-total < minDiff){
			minDiff = n-total;
			type = 1;
			mp[minDiff] = cur;
		}else if(n-total== minDiff){
			type = 2;
		}
		return;
	}
	//For the string to be processed, each time a segment of length l is intercepted from start, and the remaining strings are then DFS
	//The size of l is from 1 to s.size()-start
	for(int l = 1;l<=s.size()-start;++l){
		int it = stoi(s.substr(start,l));  //Convert string to int
		string st = cur;
		st += " ";
		st += s.substr(start,l);
		dfs(total+it, start+l, s, n,st);	
	}
}

AC code

#include<bits/stdc++.h> 
using namespace std;
map<int, string> mp; //Minimum difference → segmentation result
int type;  		//Map to different output types
int minDiff;  //Minimum difference between the calculated sum and the target number
void dfs(int total, int start, string& s, int n,string& cur){
	if(total > n){  //Boundary condition 1: total > N, which obviously does not meet the requirements
		return;
	}
	if(start == s.size()){ //Boundary condition 2: start has reached the end of the original string, that is, all the original strings have been enumerated 
		if(n-total < minDiff){
			minDiff = n-total;
			type = 1;  //The current minimum has a solution
			mp[minDiff] = cur;  //Record to map
		}else if(n-total== minDiff){
			type = 2;  //The current minimum value has more than one solution
		}
		return;
	}
	//For the string to be processed, each time a segment of length l is intercepted from start, and the remaining strings are then DFS
	//The size of l is from 1 to s.size()-start
	for(int l = 1;l<=s.size()-start;++l){
		int it = stoi(s.substr(start,l));  //string to int
		string st = cur;
		st += " ";
		st += s.substr(start,l);
		dfs(total+it, start+l, s, n,st);	
	}
}int main(){
	int n;
	string nums;
	while(cin>>n>>nums){
		if(n == 0 && nums == "0") break;
		//Initialization operation
		type = 0;
		minDiff = 9999999;  //Note that it should be large enough and greater than 999999
		mp.clear();
		string sol = "";
		
		dfs(0,0,nums,n,sol);
		
		if(type == 0)//No matter how you cut it, the sum of the number on the divided paper is greater than the target number
			cout<<"error"<<endl;
		else if(type > 1)//If there are many different cutting methods, the same optimal result can be obtained
			cout<<"rejected"<<endl;
		else
			cout<<n-minDiff<<mp[minDiff]<<endl;
	}
}

Topics: C++ Algorithm data structure string