Princess Farida on Spoj - c++

I stuck at a problem SPOJ.
I checked all the test cases passing all of them, but I am still getting "WA" on spoj.
I know it can be solved using dynamic programming, but I am practicing memoization.
Here is my code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector <int> dp(1000000);
long long int maxloot(vector<int> &loot, int n) {
if (n == 0)
return 0;
if (n == 1)
return loot[0];
if (n == 2)
return max(loot[0], loot[1]);
if (dp[n] != -1)
return dp[n];
long long int take = loot[n - 1] + maxloot(loot, n - 2);
long long int leave = maxloot(loot, n - 1);
return dp[n]= max(take, leave);
}
int main() {
int t;
cin >> t;
int p = 1;
while (t--) {
int n;
cin >> n;
vector <int> loot;
for (int i = 0; i < n; i++) {
int temp;
cin >> temp;
loot.push_back(temp);
}
dp.assign(1000000, -1);
cout <<"Case "<<p<<": "<< maxloot(loot, n)<<endl;
p++;
dp.clear();
}
}
Test case 1:
5
1 2 3 4 5
Test case 2:
1
10
output 1:
9
output 2:
10

You are using wrong data type to store value in vector dp.
As the sum of coins can go up to (10^9*10^2=10^11) therefore int would not be able to store it .Try using long long int instead as it would not lead to overflow condition.
SAME CODE AS YOURS(using long long int got accepted):
USE: vector< long long int>dp(1000000)
ACCEPTED CODE:
#include<iostream>
#include<vector>
#include<algorithm>
#define ull unsigned long long
using namespace std;
vector <long long int> dp(1000000);
long long int maxloot(vector<int> &loot, int n) {
if (n == 0)
return 0;
if (n == 1)
return loot[0];
if (n == 2)
return max(loot[0], loot[1]);
if (dp[n] != -1)
return dp[n];
long long int take = loot[n - 1] + maxloot(loot, n - 2);
long long int leave = maxloot(loot, n - 1);
return dp[n]= max(take, leave);
}
int main() {
int t;
cin >> t;
int p = 1;
while (t--) {
int n;
cin >> n;
vector <int> loot;
for (int i = 0; i < n; i++) {
int temp;
cin >> temp;
loot.push_back(temp);
}
dp.assign(1000000, -1);
cout <<"Case "<<p<<": "<< maxloot(loot, n)<<endl;
p++;
dp.clear();
}
}

Related

Top Down Approach for this dynamic programming problem

Here is the problem-
You are given array B of size n. You have to construct array A such that 1<=A[i]<=B[i] and sum of the absolute difference of consecutive pairs of A is maximized ,that is, summation of abs(A[i]-A[i-1]) is maximised.You have to return this cost.
Example B=[1,2,3] A can be [1,2,1],[1,1,3],[1,2,3] In all these cases cost is 2 which is the maximum.
Constraints n<=10^5 ,1<=B[i]<=100
Here is my approach -
Cost will be maximum when A[i]=1 or A[i]=B[i]
So I created dp[idx][flag][curr] of size [100002][2][102] where it calculates the cost till index idx. flag will be 0 or 1 representing if A[i] should be 1 or B[i] respectively. curr will be the value of A[i] depending upon flag
Here is my code
#include<bits/stdc++.h>
using namespace std;
#define boost ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef long long int ll;
#define mod 1000000007
ll n;
ll dp[100002][2][101];
ll b[100005];
ll solve(ll idx,ll flag,ll curr)
{
if(idx>=n)
return 0;
ll s1=0;
if(dp[idx][flag][curr]!=-1)
return dp[idx][flag][curr];
if(idx==0)
{
int left=solve(idx+1,0,curr);
int right=solve(idx+1,1,curr);
return dp[idx][flag][curr]=max(left,right);
}
else
{
if(flag==0)
{
s1=abs(curr-1);
return dp[idx][flag][curr]=s1+max(solve(idx+1,0,1),solve(idx+1,1,1));
}
else
{
s1=abs(b[idx]-curr);
return dp[idx][flag][curr]=s1+max(solve(idx+1,0,b[idx]),solve(idx+1,1,b[idx]));
}
}
}
int main()
{
boost
ll t;
cin>>t;
while(t--)
{
cin>>n;
memset(dp,-1,sizeof(dp));
ll res=0;
for(int i=0;i<n;i++)
cin>>b[i];
ll s1=solve(0,0,1);//Starting from idx 0 flag 0 and value as 1
ll s2=solve(0,1,b[0]);//Starting from idx 0 flag 1 and value as B[0]
cout<<max(s1,s2)<<"\n";
}
}'
Is there any way to reduce states of dp or any other top down solution because my code fails if values of B[i] are large
You implement a recursive approach. Here, a simple iterative implementation allows to get a time efficiency of O(n) and a space efficiency of O(1)
(not counting the space needed for the input array).
You correctly stated that at index i, we have two choices only, a[i]=1 (flag = 0) or a[i]=b[i] (flag = 1)
The basic idea is that, when studying what choice to make at index i, we only need to know what are the optimum sums ending at index i-1, for flag = 0 (sum0) or flag = 1 (sum1).
We don't need to explicitely calculate the array a[.].
Note: I kept long long int as in your code, but it seems that int is quite enough here.
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#define mod 1000000007 // needed ???
long long int sum_diff (const std::vector<long long> &b) {
int n = b.size();
long long int sum0 = 0;
long long int sum1 = 0;
for (int i = 1; i < n; ++i) {
long long int temp = std::max (sum0, sum1 + b[i-1] - 1); // flag = 0: a[i] = 1
sum1 = std::max (sum0 + b[i] - 1, sum1 + std::abs(b[i] - b[i-1])); // flag = 1: a[i] = b[i]
sum0 = temp;
}
return std::max (sum0, sum1);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while(t--) {
int n;
std::cin >> n;
std::vector<long long int> b(n);
for(int i = 0;i < n; i++) std::cin >> b[i];
long long int s = sum_diff (b);
std::cout << s << "\n";
}
}
As you insist to have a top-down (recursive) aproach, I have implement both approaches in the following code. But I insist that the iterative solution is better in this case.
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
int sum_diff (const std::vector<int> &b) {
int n = b.size();
int sum0 = 0;
int sum1 = 0;
for (int i = 1; i < n; ++i) {
int temp = std::max (sum0, sum1 + b[i-1] - 1); // flag = 0: a[i] = 1
sum1 = std::max (sum0 + b[i] - 1, sum1 + std::abs(b[i] - b[i-1])); // flag = 1: a[i] = b[i]
sum0 = temp;
}
return std::max (sum0, sum1);
}
void sum_diff_recurs (const std::vector<int> &b, int i, int&sum0, int &sum1) {
if (i == 0) {
sum0 = sum1 = 0;
return;
}
sum_diff_recurs (b, i-1, sum0, sum1);
int temp = std::max (sum0, sum1 + b[i-1] - 1); // flag = 0: a[i] = 1
sum1 = std::max (sum0 + b[i] - 1, sum1 + std::abs(b[i] - b[i-1])); // flag = 1: a[i] = b[i]
sum0 = temp;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while(t--) {
int n, sum0, sum1;
std::cin >> n;
std::vector<int> b(n);
for(int i = 0; i < n; i++) std::cin >> b[i];
int s = sum_diff (b);
std::cout << s << "\n";
sum_diff_recurs (b, n-1, sum0, sum1);
std::cout << std::max(sum0, sum1) << "\n";
}
}
Actually I found the solution using only two states idx and flag
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll n,k;
ll dp[100002][2];
ll b[100005];
ll solve(ll idx,ll flag)
{
if(idx>=n-1)
return 0;
if(dp[idx][flag]!=-1)
return dp[idx][flag];
ll val=(flag==1)?b[idx]:1;
ll left=solve(idx+1,0)+val-1;
ll right=solve(idx+1,1)+abs(val-b[idx+1]);
return (dp[idx][flag]=max(left,right));
}
int main()
{
ll t;
cin>>t;
while(t--)
{
cin>>n;
memset(dp,-1,sizeof(dp));
ll res=0;
for(int i=0;i<n;i++)
cin>>b[i];
ll s1=solve(0,0);
ll s2=solve(0,1);
cout<<max(s1,s2)<<"\n";
}
}

CPP Prime Generator SPOJ Sieve

I did implement Sieve prime generator. The code is pretty fast and consumes less memory. https://www.spoj.com/problems/PRIME1/
But I get "Wrong Answer" when I submit the solution. People online seem to just make the set the max to 32000 and run the solution. I don't exactly get where am I actually wrong? Or Is it just an extra newline (if possible) that makes the solution to be incorrect?
#include <iostream>
#include <unordered_map>
using namespace std;
int main(void) {
unordered_map<long long int, bool> notPrime;
notPrime[0] = true;
notPrime[1] = true;
for (long long int x = 2; x < 100000; x++) {
if (notPrime[x]) continue;
for (long long int u = 2 * x; u < 100000; u += x)
notPrime[u] = true;
}
int n;
cin >> n;
while (n--) {
long long int s, e;
cin >> s >> e;
if (s < 0)
s = 0;
for (long long int i = s; i <= e; i++) {
if (!notPrime[i]) {
cout << i << '\n';
}
}
if (n)
puts("");
}
return 0;
}

Floating point Exception in c++ because of divide statement

I have searched google but I was unable to find the solution to my problem.
Here is my code-
#include <bits/stdc++.h>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
using namespace std;
long long buyMaximumProducts(int n, long k, vector <int> a) {
// Complete this function
vector<pair<int, int>> p;
long i;
for(i=0; i<n; i++) {
p.push_back(make_pair(a[i], i+1));
}
sort(p.begin(), p.end());
if(k < p[0].first)
return 0;
long long sum=0,stocks=0;
for(i=0;i<n;i++)
{
if((sum+p[i].first*p[i].second) <= k)
{
sum+=p[i].first*p[i].second;
stocks+=p[i].second;
}
else
break;
}
long long amtleft=k-sum;
**stocks+=(long long)(amtleft/p[i].first);**
return stocks;
}
int main() {
int n;
cin >> n;
vector<int> arr(n);
for(int arr_i = 0; arr_i < n; arr_i++){
cin >> arr[arr_i];
}
long long k;
cin >> k;
long long result = buyMaximumProducts(n, k, arr);
cout << result << endl;
return 0;
}
I'm getting floating point exception. I think the error is coming because of the star statement. Can anyone please tell me what could be the plausible reason and how to remove it?
The program contains at least 3 fault.
long long k;
cin >> k;
long long result = buyMaximumProducts(n, k, arr);
long long buyMaximumProducts(int n, long k, vector <int> a) {
k is 'long long' but parameter k is only 'long'.
for(i=0;i<n;i++) {
if((sum+p[i].first*p[i].second) <= k) {
sum+=p[i].first*p[i].second;
stocks+=p[i].second;
} else
break;
}
if we never get to the 'break' then 'i' is not valid for
stocks+=(long long)(amtleft/p[i].first);
causing an exception.
and if
p[i].first
is zero you get an divide by zero exception.

SPOJ ETF c/c++ code

I am doing a question in spoj http://www.spoj.com/problems/ETF/ . I submitted this code.
#include <iostream>
using namespace std;
int fi(int);
int main()
{
int t,n;
cin>>t;
while(t--)
{
cin>>n;
printf("%d\n",fi(n));
}
}
int fi(int n)
{
int result = n;
for(int i=2;i*i <= n;i++)
{
if (n % i == 0) result -= result / i;
while (n % i == 0) n /= i;
}
if (n > 1) result -= result / n;
return result;
}
ACCEPTED IN: 0.60 sec.
I want to know one thing
Why my code got accepted in c++4.3.2 while i was using a printf?

Minimum difference in an array

I want to find the minimum difference among all elements of an array. I read through various other questions, but couldn't find the exact source of the error in the following code.
#include<iostream>
#include<stdio.h>
#include<cstdlib>
using namespace std;
void quicksort(long int *lp, long int *rp);
int main()
{
int t,n;
long int s[5000];
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++) cin>>s[i];
quicksort(&s[0],&s[n-1]);
//cout<<"passes:"<<passes<<endl;
//for(int i=0;i<n;i++) cout<<s[i]<<" ";
long int min = abs(s[1]-s[0]);
//cout<<endl<<min;
for(int i=1;i<(n-1);i++){
long int temp = abs(s[i]-s[i+1]);
if (temp <= min) min = temp;
}
cout<<min;
}
}
void quicksort(long int *lp,long int *rp){
int arraysize= (rp-lp)+1;
if(arraysize > 1){
long int *pivot = (lp+(arraysize/2));
long int swap=0;
long int *orgl = lp;
long int *orgr = rp;
while(lp!=rp){
while (*lp < *pivot) lp++;
while (*rp > *pivot) rp--;
if (lp == pivot) pivot=rp;
else if (rp == pivot) pivot=lp;
swap = *lp;
*lp = *rp;
*rp = swap;
if((*lp == *pivot) || ( *rp == *pivot)) break;
}
quicksort(orgl,pivot-1);
quicksort(pivot+1,orgr);
}
}
The problem statement is given in this link : http://www.codechef.com/problems/HORSES
Can you please identify the error in my program ?
You are using C++ so instead of using your custom quicksort which is not really guarantee O(n*logn) you better use sort from <algorithm>.
This logic looks good:
long int min = abs(s[1]-s[0]);
//cout<<endl<<min;
for(int i=1;i<(n-1);i++){
long int temp = abs(s[i]-s[i+1]);
if (temp <= min) min = temp;
}
By the way:
cout<<min;
Add cout<<min << endl;
The line
if((*lp == *pivot) || ( *rp == *pivot)) break;
is wrong. Consider
5 4 7 5 2 5
^
pivot
Oops.
This line
long int temp = abs(s[i]-s[i+1]);
is unnecessarily complex. Since the array is (supposedly) sorted,
long int temp = s[i+1] - s[i];
does the same without calling abs.
sort(s, s + n); // #include <algorithm> O(n*log n)
Otherwise sort/find minimum algorithm is correct. There are O(n) algorithms based on randomization, bucket sort.
#include <algorithm> // sort()
#include <iostream>
int main() {
using namespace std;
int ntests, n;
const int maxn = 5000; // http://www.codechef.com/problems/HORSES
int s[maxn];
cin >> ntests; // read number of tests
while (ntests--) {
cin >> n; // read number of integers
for (int i = 0; i < n; ++i) cin >> s[i]; // read input array
sort(s, s + n); // sort O(n*log n)
// find minimal difference O(n)
int mindiff = s[1] - s[0]; // minn = 2
for (int i = 2; i < n; ++i) {
int diff = s[i] - s[i-1];
if (diff < mindiff) mindiff = diff;
}
cout << mindiff << endl;
}
}
#include <iostream> using namespace std;
int main() {
int a[] = {1,5,2,3,6,9};
int c=0;
int n = sizeof(a)/sizeof(a[0]);
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
cout<<a[i]<<" - "<<a[j]<<" = "<<a[i]-a[j]<<endl;
if(abs(a[i]-a[j]) == 2)
c++;
}
}
cout<<c<<endl;
return 0; }