Solving a dp problem from codeforces - Cut Ribbon - c++

I was trying to solve this problem and from the comments section in the editorial, I was directed to the following solution :
#include <bits/stdc++.h>
using namespace std;
#define MAX(a,b,c) max(a,max(b,c))
int n,a,b,c,dp[4001];
int f(int x)
{
if (x == 0) return 0;
if (x < 0 || (x > 0 && x < a && x < b && x < c))
return 0xACCE97ED; // <- **I have doubt here**
if (!dp[x]) dp[x] = MAX(f(x-a),f(x-b),f(x-c)) + 1;
return dp[x];
}
int main()
{
cin >> n >> a >> b >> c;
memset(dp,0,sizeof(dp));
cout << f(n) << endl;
}
I wanted to know:
What is the need of the if statement that returns 0xACCE97ED for the test case:
4000 1 2 3. This test case dosen't work when that specific if statement is missing.
Why specifically 0xACCE97ED is being returned? Because when I tried to return any other number (say 9999), then the output is expected output + 9999.

if (x < 0 || (x > 0 && x < a && x < b && x < c))
return 0xACCE97ED; // -1395746835
Well looking at the dp function, it is basically maximizing values and this specific if statement is saying:
if x < 0
the length of the ribbon you cut is negative (which should be impossible)
or if x > 0 and x < a, b, c which means you can still cut X but all available sizes would result into having a ribbon of negative length
return 0xACCE97ED; return a random negative value which happens to spell out ACCEPTED because this state is invalid
And since the third if statement will try to get the max value, 0xACCE97ED will never be selected as the max value.

0xACCE97ED means "ACCEPTED" in the 1ee7 speech. nothing else specific about this value.

What is the need of the if statement that returns 0xACCE97ED for the test case: 4000 1 2 3
if (x < 0 || (x > 0 && x < a && x < b && x < c))
return 0xACCE97ED; // <- **I have doubt here**
because the function f is recursive, in the next line it calls itself:
if (!dp[x]) dp[x] = MAX(f(x-a),f(x-b),f(x-c)) + 1;
return dp[x];
with a smaller values for x so presumable it will eventually make that if statement true and will return "accepted" (0xACCE97ED).

Related

How to get all models or all convex evaluation?

I'm new to the Z3-Solver with API in C++ and want to solve a group of inequalities and find the results.
I've read the answer which written in Python and try to write it in C++, but it repeating prints one model.
5 <= x + y + z <= 16
AND -4 <= x - y <= 6
AND 1 <= y - z <= 3
AND -1 <= x - z <= 7
AND x >= 0 AND y >= 0 AND z >= 0
The inequalities were added into the solver, and have a lot of evaluations.
c is context and s is the solver.
vector<const char*> variables {"x", "y", "z"};
// ...
// till here, s was added into several constraints
while(s.check() == sat){
model m = s.get_model();
cout << m << "\n######\n";
expr tmp = c.bool_val(false);
for(int i = 0; i < variables.size(); ++ i){
tmp = tmp || (m[c.int_const(variables[i])] != c.int_const(variables[i]));
}
s.add(tmp);
}
And the result:
(define-fun z () Int
0)
(define-fun y () Int
2)
(define-fun x () Int
3)
######
(define-fun z () Int
0)
(define-fun y () Int
2)
(define-fun x () Int
3)
######
(define-fun z () Int
0)
...
And it just print one model. I'm not sure where is wrong.
How can I get all models or get one or more convex sets (such as {l1 <= x <= u1 and l2 <= x - y <= u2 and ...}), but not to traverse all evaluations.
BTW, there's a lot tutorials on python(such as this), where I can learn z3 in c++ as the example and api doc. is not easy to get started.
Your "model refutation" loop isn't quite correct. Since you didn't post your whole code, it's hard to tell if there might be other issues, but this is how I would go about it:
#include<vector>
#include"z3++.h"
using namespace std;
using namespace z3;
int main(void) {
context c;
expr_vector variables(c);
variables.push_back(c.int_const("x"));
variables.push_back(c.int_const("y"));
variables.push_back(c.int_const("z"));
expr x = variables[0];
expr y = variables[1];
expr z = variables[2];
solver s(c);
s.add(5 <= x+y+z);
s.add(x+y+z <= 16);
s.add(-4 <= x-y);
s.add(x-y <= 6);
s.add(-1 <= x-z);
s.add(x-z <= 7);
s.add(x >= 0);
s.add(y >= 0);
s.add(z >= 0);
while (s.check() == sat) {
model m = s.get_model();
cout << m << endl;
cout << "#######" << endl;
expr tmp = c.bool_val(false);
for(int i = 0; i < variables.size(); ++i) {
tmp = tmp || (variables[i] != m.eval(variables[i]));
}
s.add(tmp);
}
return 0;
}
This code runs and enumerates all the "concrete" models. From your question, I surmise you're also wondering if you can get "symbolic" models: That's not possible with an SMT solver. SMT solvers only produce concrete (i.e., all ground term) models, so if you need to generalize from them, you'll have to do that outside of the z3 boundary.

After input my program seems to skip the first IF statement and go directly to ELSE

I have a problem with the code. It compiles with no errors, but right after taking input from the user it even with correct values it seems to skip the first conditional statement and go directly to ELSE which causes the program to terminate. I can't seem to find the cause for this behavior.
I think it might the issue with the way the conditional statement is constructed:
if( ((S <= 25 && S <= 75) % 5 == 0) && (U < 0.2 && U < 0.7) ){
I need to check if the value entered is 25 <= S <= 75 and is divisible by 5, as well as the other value being 0.2 < U < 0.7
Course Assignment
//#include "stdafx.h" // Header File used VS.
#include <iostream>
//#include <iomanip> // Used to format the output.
#include <cstdlib> // Used for system().
#include <math.h> // Used for sqrt().
using namespace std;// ?
int main (){
int S; // Gram/Litre
double U; // Specific Max. Growth Rate. Per Hour.
double D; // Maximum Dilution Rate.
const int K = rand() % 7 + 2; // Saturation Constant - Randomly Gegerated Number Between 2 & 7. In Hour/Litre.
cout << "Enter value between 25 and 75, divisible by 5, for S in Gram/Litre: ";
cin >> S;
cout << "Enter value bigger than 0.2, but less than 0.7, for U per Hour: ";
cin >> U;
if( ((S <= 25 && S <= 75) % 5 == 0) && (U < 0.2 && U < 0.7) ){ // Check Condition ***May Need Adjustments***
D = U * ( 1 - sqrt ( K / ( K + S) ) ); // Might have to adjust values to fit data type double. Add .00
cout.precision(3); // Prints 3 values after decimal point.
cout << "Maximum dilution rate is: " << D << endl;
if( D < 0.35 && D < 0.45 ){
cout << "Kinetic parameters are acceptable." << endl;
}
else{
cout << "Kinetic parameters are not acceptable." << endl;
}
}
else{
cout << "Invalid Input. Program will now terminate." << endl;
}
system("PAUSE"); // Pauses the program before termination.
return 0;
}
First, if you want 25 <= S <= 75, you should have
25 <= S && S <= 75, not S <= 25 && S <= 75. Same with U < 0.2 and D < 0.35 - they should be 0.2 < U and 0.35 < D.
Second, the above statement returns a boolean - thus, if S is a value between 25 and 75, the boolean will be cast to an integer value of 1, and 1 % 5 == 0 always be false. (Similarly, if S is outside this range, the boolean will be cast to an integer 0 and 0 % 5 == 0 will always be true)
A correct, complete if-statement is as follows:
if((25 <= S && S <= 75) && (S % 5 == 0) && (0.2 < U && U < 0.7)){
...
if(0.35 < D && D < 0.45){
...
}
...
}
If you read a number between 25 and 75 from the input, the if( ((S <= 25 is always false.
You must use if( ((S >= 25 && ....
The problem mainly lies in your loop conditions. For example, in this line from your code:
if( ((S <= 25 && S <= 75) % 5 == 0) && (U < 0.2 && U < 0.7) ){
//...
}
The if condition S <= 25 && S <= 75 simply can be rewritten as S <= 25 because in words, your parameter states that if S is less than or equal to 25 OR if S is less than or equal to 75, and so on.
The same problem exists here: U < 0.2 && U < 0.7. Once again, the if statement simply checks whether U is less than 0.2 and U is less than 0.7, the latter always being true if the former is true.
However, in your output statement before accepting the 2 inputs, you state that S should have a range of 25 <= S <= 75, meaning that S is greater than 25; not less. The same issue for U: you are expecting input ranging between 0.2 < U < 0.7.
How you should rewrite your if-then statement is as follows:
if( (S >= 25 && S <= 75) && (S % 5 == 0) && (U > 0.2 && U < 0.7) ){
//...
}
This not only makes your if-statement's conditions easier to read and comprehend, but it also eliminates the errors. This should work now. The meaning of the code stays the same: S has to be between 25 and 75 (including these numbers), it should be divisible by 5, and U should be between 0.2 and 0.7.
BTW, the same mistake exists in this part of your code also:
if( D < 0.35 && D < 0.45 ){...
I fixed it below:
if( D > 0.35 && D < 0.45 ){...
Good luck!

C++ Checking if a double is within .1 of another double (+/-)

I'm running a bit of code where I need to compare two 2D arrays for any variance. I've tried using the following line of code to check and compare the values, but the test fails every time = if(arr1[a][b] != arr2[a][b] || arr1[a][b] + .1 != arr2[a][b] || arr1[a][b] - .1 != arr2[a][b]) {.
I know this is failing because of the || statement, because one of the requirements is met. So I've got to find another way to determine if the double stored in a specific location in the array matches the other array in the parallel location.
Here's my full code:
int numberOfFailedCompares = 0;
for(int a = 0; a < 20; a++) {
int b = 0;
while(b < 20) {
if(arr1[a][b] != arr2[a][b] || arr1[a][b] + .1 != arr2[a][b] || arr1[a][b] - .1 != arr2[a][b]) {
numberOfFailedCompares++;
cout << numberOfFailedCompares << endl;
}
b++;
}
}
Is there a statement in C++ which will allow me to check if the value is within the +/- .1 threshold? Something like
if(arrLocation1 (+/- .1) == arrLocation1) {
...
}
"Variance" means "within X", and not "equal to something plus X or something minus X". Instead of comparing for equality, you compare for less/greater than your variance. So, for example, to test for variance of +/- .1:
if (b >= a-.1 && b <= a+.1)
How about this?
#define eps .1
...
if( fabs(x-y) <= eps )
...

Could someone tell me any different way to make this code faster?

The code runs correctly and it does what it is supposed to do, but I was told I could make it faster by using Boolean expressions instead but would not really know where to insert them here. The problem is:
Given a sequence of n points with their coordinates, write a program remote, which calculates the value of the smallest remoteness of a point, which is outside the square. A point is outside the square, if it is neither inner to the square, nor belongs to square contour. If there are no points outside the square, your program has to output 0.
Constraints:
1 ≤ n ≤ 10000 and 1 ≤ a ≤ 1000 ;
Example:
Input:
5 4
1 2
4 6
-3 2
-2 2
4 -1
Output: 5
Could someone suggest me any technique to make the code more efficient?
int remote(int x, int y) {
int z = abs(x) + abs(y);
return z;
}
int main() {
int n, a;
int x;
int y;
cin >> n >> a;
int z=20001;
for (int i = 1; i <= n; i++) {
cin >> x >> y;
if (x > a / 2 || y > a / 2) {
if (z > remote(x, y)) {
z = remote(x, y);
}
}
}
cout << z <<endl;
return 0;
}
For one, you are calling remote twice (in some cases) needlessly.
Consider using this:
#include <algorithm>
z = std::max(z, remote(x, y));
This will also shorten and clarify the code.
Also, it's possible the divisions are slow. Try (after profiling!) replacing
x > a / 2 || y > a / 2
by
(x << 1) > a || (y << 1) > a
Note #Donnie & others claims in the comments that compilers will do the latter optimization, and they are probably correct.
I would like to show you the timings on my machine:
Version 1:
for (int i = 1; i <= n; i++) {
cin >> x >> y;
if (x > a / 2 || y > a / 2) {
if (z > remote(x, y)) {
z = remote(x, y);
}
}
}
Version 2:
for (int i = 1; i <= n; i++) {
cin >> x >> y;
/* if (x > a / 2 || y > a / 2) {
if (z > remote(x, y)) {
z = remote(x, y);
}
}
*/
}
For n=10^5, compiled with -O3 both yield 60ms. Compiled without optimization: both 60ms.
First step for optimizing is to know where your program spends time. Reading/parsing the data is the bottle neck.
You could speed up it a little bit by adding as first line to your main:
ios_base::sync_with_stdio(false);
On my machine I'm down to 20ms.
1) Assign a temporary value to the remote function:
if (x > a / 2 || y > a / 2)
{
const int r = remote(x,y);
if (z > r)
{
z = r;
}
}
2) Replace the call to remote with the contents of remote, removing the overhead of a function call:
if (x > a / 2 || y > a / 2)
{
const int r = abs(x) + abs(y);
if (z > r)
{
z = r;
}
}
3) Replace a / 2 with a constant temporary variable:
const int midpoint = a >> 1;
if (x > midpoint || y > midpoint)
4) Change compiler optimization level to high - for speed.
5) The bottleneck is now in the input statement. Any gain by optimizing the remainder of the loop is wasted by the Input time. There is no more Return On Investment for further changes.

Finding MAX of numbers without conditional IF statements c++ [duplicate]

This question already has answers here:
Mathematically Find Max Value without Conditional Comparison
(18 answers)
Closed 9 years ago.
So i have too get two numbers from user input, and find the max of the two numbers without using if statements.
The class is a beginner class, and we have too use what we already know. I kinda worked something out, but it only works if the numbers are inputted with the max number first.
#include <iostream>
using namespace std;
int main()
{
int x = 0, y = 0, max = 0;
int smallest, largest;
cout << "Please enter 2 integer numbers, and i will show you which one is larger: ";
cin >> x >> y;
smallest = (x < y == 1) + (x - 1);
smallest = (y < x == 1) + (y - 1);
largest = (x < y == 1) + (y - 1);
largest = (y > x == 1) + (x + 1 - 1);
cout << "Smallest: " << smallest << endl;
cout << "Largest: " << largest << endl;
return 0;
}
Thats what i have so far, but after putting different test data in, i found out it only works for numbers such as 4,5 or 6,7. But numbers with more then 2 spaces between eachother they dont such as, 4,8 or 5, 7. Any help would be appreciated.
I saw this question in Cracking the Coding interview book.
Let’s try to solve this by “re-wording” the problem We will re-word the problem until we get something that has removed all if statements
Rewording 1: If a > b, return a; else, return b
Rewording 2: If (a - b) is negative, return b; else, return a
Rewording 3: If (a - b) is negative, let k = 1; else, let k = 0 Return a - k * (a - b)
Rewording 4: Let c = a - b Let k = the most significant bit of c Return a - k * c
int getMax(int a, int b) {
int c = a - b;
int k = (c >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1;
int max = a - k * c;
return max;
}
Source: http://www.amazon.com/Cracking-Coding-Interview-Programming-Questions/dp/098478280X
Edit: This code works even when a-b overflows.
Let k equal the sign of a-b such that if a-b >=0, then k is 1, else k=0.Let q be the inverse of k. Above code overflows when a is positive or b is negative, or the other way around. If a and b have different signs, then we want the k to equal sign(a).
/* Flips 1 to 0 and vice-versa */
public static int flip(int bit){
return 1^bit;
}
/* returns 1 if a is positive, and 0 if a is negative */
public static int sign(int a){
return flip((a >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1);
}
public static int getMax(int a, int b){
int c = a - b;
int sa = sign(a-b); // if a>=0, then 1 else 0
int sb = sign(a-b); // if b>=1, then 1 else 0
int sc = sign(c); // depends on whether or not a-b overflows
/* If a and b have different signs, then k = sign(a) */
int use_sign_of_a = sa ^ sb;
/* If a and b have the same sign, then k = sign(a - b) */
int use_sign_of_c = flip(sa ^ sb);
int k = use_sign_of_a * sa + use_sign_of_c * sc;
int q = flip(k); //opposite of k
return a * k + b * q;
}
Here is a funny solution:
int max_num = (x>y)*x + (y>=x)*y;
Assuming that you have covered bitwise operators already you can do this:
max = a-((a-b)&((a-b)>>(sizeof(int)*8-1)));
This is based off of the solution from Mathematically Find Max Value without Conditional Comparison that #user93353 pointed out in the comments above.
This may be overkill if you really are just trying to avoid if statements, not comparisons in general.
You can try this code to find max and min for two input variables.
((a > b) && (max = a)) || (max=b);
((a < b) && (min = a)) || (min=b);
For three input variables you can use similar method like this:
int main()
{
int a = 10, b = 9 , c = 8;
cin >> a >> b >> c;
int max = a, min = a;
// For Max
((a > b) && (a > c) && (max=a)) ||
((b > c) && (b > a) && (max=b)) ||
(max=c) ;
// For min
((a < b) && (a < c) && (min=a)) ||
((b < c) && (b < a) && (min=b)) ||
(min=c) ;
cout << "max = " << max;
cout << "and min = " << min;
return 1;
}
One run is:
:~$ ./a.out
1
2
3
max = 3 and min = 1
Edit
Thanks to #Tony D: This code will fail for negative numbers.
One may try this for negative numbers for two inputs to find max(not sure for this):
((a > b) && ( a > 0 && (max = a))) || ((b > a) && (max = b)) || (max = a);