The problem I am trying to solve is the following: I get N rectangular paper strips with 1cm width and length C. I need to cut the strips at a height where the sum of the areas of the cut strip is equal to A. You can see an example bellow for which N = 5, the strips are of length, 5,3,6,2 and 3 cm and A = 3cm where the cut is made at 4cm.
Note that I'm looking here for the red area.
The input is given as follows. The first line in each case begins with two integers N (1 ≤ N ≤ 10^5) and A (1 ≤ A ≤ 10^9) representing respectively the number of strips and the expected resulting area. The next line contains N integers, representing the length C_i (1 <= C_i <= 10^4) of each strip. The input ends with A = C = 0, which should not be processed.
For each test case, output a single line, the height H of the cut that must be done so that the sum of the area of the cut strips is equal to A cm². Print the answer with 4 decimal places. Output ":D" if no cutting is required, or "-.-" if it’s impossible.
This problem can be found here
My idea for solving this problem was to use a binary search where I pick a height in the middle of the strips and make it larger or smaller depending on whether my cut was too high or too low. My implementation of the problem is given bellow:
#include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>
using namespace std;
int main(){
vector<int> v; // Vector that holds paper heights
int n; // Number of papers
double h, // Height of the cut
sum, // Area sum
min_n, // Minimum height for cut to happen
max_n, // Maximum height for cut to happen
a; // Desired final area
// Set desired output
cout << fixed << setprecision(4);
/* Get number of papers and desired area,
terminates if N = A = 0
*/
while(cin >> n >> a && (n||a)){
v.resize(n); // Resize vector to fit all papers
// Get all paper sizes
for(int i=0;i<n;i++){
cin >> v[i];
}
/* Sort the vector in decreasing order to
simplify the search
*/
sort(v.begin(),v.end(),greater<int>());
max_n = v[0]; // Largest possible cut is at the height of the largest paper
min_n = 0; // Smallest possible cut is at the base with height 0
// Iterate until answer is found
while(true){
// Initialize cut height as the average of smallest and largest cut sizes
h = (min_n + max_n)/2;
/* The area sum is equal to the sum of the areas of each cut, which is
given by the height of the paper minus the cut height. If the cut is
higher than the paper, the cut has area 0.
*/
sum = 0;
for(int i=0; i<n;i++){
if(v[i] <= h) break; // From here onward cut area is 0 and there is no point adding
sum += v[i]-h;
}
// If the error is smaller than the significant value, cut height is printed
if(abs(sum-a) < 1e-5){
// If no cut is needed print :D else print cut height
(h < 1e-4 ? cout << ":D" << endl : cout << h << endl);
break;
}
// If max_n is "equal" to min_n and no answer was found, there is no answer
else if(max_n - min_n < 1e-7){
cout << "-.-" << endl;
break;
}
// Reduces search interval
sum < a ? max_n = h : min_n = h;
}
}
return 0;
}
The problem is, after submitting my answer I keep getting a 10% error. The website has a tool for comparing the output of you program with the expected output so I ran a test file with over 1000 randomly generated test cases and when I compared both I got a rounding error on the 4th decimal case, unfortunately, I don't have the file nor the script to generate test cases for me anymore. I tried changing the acceptable error to a smaller one but that didn't work. I can't seem to find the error, does any of you have an idea of what is happening?
Aucun commentaire:
Enregistrer un commentaire