Knapsack Dynamic Programming - Need help on problem (Roller Coaster Fun) - c++

I recently started learning Dynamic Programming, and am currently trying to solve "Roller Coaster Fun" on Kattis. However, I'm only getting 10/30 test cases (wrong answer on test case 11), and am stuck on what I am doing wrong.
My thinking is very similar to the coin problem (7.1 in the CPH, scroll down to "Coin Problem"), where we find the answer for each of the 25,000 times using the previous ones:
(this is pseudocode)
// fun[i] is the maximum amount of fun possible at time i
// k[i][j] is the number of times Jimmy goes on coaster j at time i
// all other functions/variables are as given in the problem
fun[1] = 0
fun[n] = max(fun[n - 1], // last fun value (don't go on any new ride)
fun[n - t[0]] + f(0, k[n][0]),
...,
fun[n - t[i]] + f(i, k[n][i]),
...,
fun[n - t[N - 1]] + f(N - 1, k[n][N - 1]))
Here is my full code:
// https://open.kattis.com/problems/rollercoasterfun
#include <bits/stdc++.h>
using namespace std;
#define MAX_N 100
#define MAX_T 25000
vector<int> a(MAX_N), b(MAX_N), t(MAX_N);
vector<int> dp(MAX_T + 1);
vector<vector<int>> k(MAX_T + 1, vector<int>(MAX_N));
int f(int time, int i)
{
return max(0, a[i] - k[time][i] * k[time][i] * b[i]);
}
int main()
{
int N;
cin >> N;
for (int i = 0; i < N; ++i)
cin >> a[i] >> b[i] >> t[i];
dp[0] = 0;
fill(k[0].begin(), k[0].end(), 0);
for (int time = 1; time <= MAX_T; ++time)
{
dp[time] = dp[time - 1];
k[time] = k[time - 1];
for (int i = 0; i < N; ++i)
{
if (time - t[i] >= 0)
{
int newFun = dp[time - t[i]] + f(time - t[i], i);
if (newFun > dp[time])
{
dp[time] = newFun;
k[time] = k[time - t[i]];
++k[time][i]; // go on this ride one more time
}
}
}
// cout << time << ' ' << dp[time] << '\n';
}
int Q;
cin >> Q;
int q;
for (int i = 0; i < Q; ++i)
{
cin >> q;
cout << dp[q] << '\n';
}
return 0;
}
Any help would be appreciated!

Related

Possible cause for "Runtime Error" in the following code?

I'm currently practising the kickstart coding challenges by google. here is a link to see the question :
https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050e01/00000000000698d6
I have made the program which succeeded giving the right answer using the sample question which the question provided but when I actually submit it for checking, the code met a runtime error. Since it won't give why so, I have no idea how to proceed. So I hope you guys can help...
Here is the code:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int ts;
cin >> ts;
for (int i = 1; i <= ts; ++i)
{
int n, p;
cin >> n >> p;
// input skill level and sort descending
int skill[100] = {0};
for (int i = 0; i < n; i++) cin >> skill[i];
int size = sizeof(skill) / sizeof(skill[0]);
sort(skill, skill + size, greater<int>());
int ans= 9999999;
for (int i = 0; i <=(n-p); i++)
{
int tmp = 0;
for (int j = i + 1; j <= i + (p - 1); j++)
tmp += skill[i] - skill[j];
ans = min(ans, tmp);
}
cout << "Case #" << i << ": " << ans << endl;
}
}
So the question says that N can be upto 10000, but your code assumes that it is no bigger than 100.
Regarding LTE, you are almost there. Try to replace the
for (int j = i + 1; j <= i + (p - 1); j++)
tmp += skill[i] - skill[j];
loop with the constant time expression. Hint: when the most skillful player leaves the window, by how much the training time for the rest players gets decreased?

Implementing Merge Sort in C++ using Vectors

I wanted to do an implementation of Merge Sort in C++. I didn't look at concrete examples because I wanted to try out for myself. And here is what I came up with using vectors:
int *mergeSort(int *a, int n) {
//some debugging info for me
cout << "Merge Sort called with: ";
for(int i = 0; i < n; i++){
cout << *(a + i) << " ";
}
cout << " and size: " << n << endl;
//base case
if (n == 1) {
return a;
}
//spliting the arrays
vector<int> firstArray(a, a + n/2);
vector<int> secondArray(a + n/2, a + n);
int *firstResultPointer = mergeSort(&(firstArray[0]), firstArray.size());
vector<int> resultFirst(firstResultPointer, firstResultPointer + n/2);
int *secondResultPointer = mergeSort(&(secondArray[0]), secondArray.size());
vector<int>resultSecond(secondResultPointer, secondResultPointer + n / 2);
vector<int> resultArray(n);
int i = 0;
int j = 0;
while (i + j < n) {
//when exit the size of the vector
if(firstArray.size() <= i){
while(j < secondArray.size()){
resultArray[(i + j)] = secondArray[j];
j++;
}
break;
}
else if (secondArray.size() <= j){
while(i < firstArray.size()){
resultArray[(i + j)] = firstArray[i];
i++;
}
break;
}
else {
//normal case merge
if (firstArray[i] < secondArray[j]) {
resultArray[(i + j)] = firstArray[i];
i++;
}
else {
resultArray[(i + j)] = secondArray[j];
j++;
}
}
}
return &(resultArray[0]);
}
a is a pointer to the vector and n is the length of the same vector. I had quite a lot of trouble in the merging because it would leave the vector and start using 0. I think I fixed that based on my debugging. However, when I debug after I get to the lowest level and then starting going back up it just starts jumping all over the place and I cannot follow it. Using cout I printed to see what arguments are passed to the merge sort and they seem to be correct. Can anyone tell me where the problem is?

Bubble sort issue

Currently studying software engineering at college (first year) and made a program where the user enters how many entries there will be and then they input the times for each entry and it is sorted in descending order.
The problem I am having is when I enter a large number for the first input it doesn't sort correctly but the rest do. It would be great if someone could help me out with this and sorry for the noob question:P
The entire code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int TotalSize = 0;
void getSpeed(int *CalculationTime, int NoOfCalculations)
{
for (int i = 0; i < NoOfCalculations; i++)
{
cout << "Please enter the speed of calculation " << i + 1 << "(Ms): "; cin >> CalculationTime[i];
}
}
void sort_speeds(int *CalculationTime, int NoOfCalculations)
{
// Sorting speeds in decending order
bool swapped = true;
int i, j = 0;
int temp;
while (swapped)
{
swapped = false;
j++;
for (i = 1; i < NoOfCalculations - j; i++)
{
if (CalculationTime[i] > CalculationTime[i + 1])
{
temp = CalculationTime[i];
CalculationTime[i] = CalculationTime[i + 1];
CalculationTime[i + 1] = temp;
swapped = true;
}
}
}
// Output times decending order
for (int i = 0; i < NoOfCalculations; i++)
{
cout << CalculationTime[i] << "\n";
}
}
int main()
{
// Declaring & Initializing variables
int NoOfCalculations = 0;
int *CalculationTime = new int[NoOfCalculations];
// Getting user input
cout << "How many calculations are there? "; cin >> NoOfCalculations;
getSpeed(CalculationTime, NoOfCalculations);
// Sorting and displaying times
sort_speeds(CalculationTime, NoOfCalculations);
system("pause");
return 0;
}
You've never compare first element of your array with anything - for (i = 1; i < NoOfCalculations - j; i++) should be for (i = 0; i < NoOfCalculations - j; i++)
The issue is for (i = 1; i < NoOfCalculations - j; i++) You are starting at position 1, start at position 0 and it fixes the problem. for (i = 0; i < NoOfCalculations - j; i++)
// Declaring & Initializing variables
int NoOfCalculations = 0;
int *CalculationTime = new int[NoOfCalculations];
// Getting user input
cout << "How many calculations are there? "; cin >> NoOfCalculations;
Bzzzt. You allocate a zero-element array, and then don't reallocate it. I bet if you entered a large enough number for your number of calculations, your program would crash.
Really, you want to be using std::vector, an extremely useful datastructure, the use of which is a bit outside of the scope of this answer. Basically, you can do stuff like this:
std::vector<int> getSpeeds(int NoOfCalculations)
{
std::vector<int> speeds;
for (int i = 0; i < NoOfCalculations; i++)
{
int speed;
std::cout << "Please enter the speed of calculation " << i + 1 << "(Ms): ";
std::cin >> speed;
speeds.push_back(speed);
}
return speeds;
}
You can use the returned vector almost exactly as if it were an array:
std::vector<int> speeds = getSpeeds(10);;
if (CalculationTime[3] > CalculationTime[4])
// do something
Often, in a C++ application, the explicit use of pointers is a sign that you're not using the standard library, and as a result making life much, much harder for yourself.
Oh, and also:
for (i = 1; i < NoOfCalculations - j; i++)
You never look at NoOfCalculations[0] or NoOfCalculations[i - 1], so you never touch the first element.
while (swapped)
{
swapped = false;
j++;
for (i = 0; i < NoOfCalculations - j; i++) //try and start i from 0. I think you are missing the first element to check
{
if (CalculationTime[i] > CalculationTime[i + 1])
{
temp = CalculationTime[i];
CalculationTime[i] = CalculationTime[i + 1];
CalculationTime[i + 1] = temp;
swapped = true;
}
}
}

Trying to figure out an issue with corrupted stack while adding int arrays in c++

I am working on visual studio 2013, with a windows8 hp.My code is trying to add two int arrays of size [20] and output the sum. I know I am out or range some where ,but I can't seem to find where. I am the first digit from each array during my convert function and my answer[i] output is only 19 digits when it should be 21digits.
#include<iostream>
#include<string>
#include<cmath>
#include<cstring>
using namespace std;
int globalnum[20];
int total[21];
int i;
void convert(char[], int);
void add(int[], int[], int);
void printAnswer(int[], int);
int main()
{
char n1[20];
char n2[20];
int num1[20];
int num2[20];
int answer[21];
cin >> n1 >> n2;
int l1 = strlen(n1);
int l2 = strlen(n2);
int max = fmax(l1, l2);
convert(n1, l1);
for (int i = 0; i < max - 1; i++)
num1[i] = globalnum[i];
for (int i = 0; i < max; i++)
cout << num1[i];
cout << endl;
convert(n2, l2);
for (int i = 0; i < max - 1; i++)
num2[i] = globalnum[i];
for (int i = 0; i < max; i++)
cout << num2[i];
cout << endl;
add(num1, num2, max);
for (int i = 0; i < max - 1; i++)
answer[i] = total[i];
// printAnswer(answer,max);
for (int i = 0; i < max - 1; i++)
cout << answer[i];
return 0;
}
void convert(char c1[], int size)
{
for (int i = 0; i < size - 1; i++)
globalnum[i] = c1[size - 1 - i] - '0';
}
void add(int add1[], int add2[], int s1)
{
int sum[21];
int remain = 0;
for (i = 0; i < s1 - 1; i++)// This starts to add the numbers.
{
sum[i] = (add1[s1 - 1 - i] + add2[s1 - 1 - i] + remain) % 10;
if (add1[s1 - 1 - i] + add2[s1 - 1 - i] + remain >= 10)
remain = 1;
else
remain = 0;
if (remain != 0)
total[s1 - 1 - i] = 1;
else total[s1 - 1 - i] = 0;
total[s1 - 1 - i] = sum[i];
}
if (remain != 0)
total[0] = 1;
}
//void printAnswer(int t[], int b)
// {
// for (int i = b - 1; i < 0; i--)
// cout << t[i];
// }
// cout << endl;
//}
There's too many problems with your code to give a simple answer. It's maybe easier to work backwards from working code. You haven't fully specified the problem but this was my best guess at what you're trying to do:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
vector<int> toInts(const string& s) {
vector<int> v(s.size());
transform(cbegin(s), cend(s), begin(v), [](int c) { return c - '0'; });
return v;
}
int main() {
string a, b;
cin >> a >> b;
auto n = toInts(a);
auto m = toInts(b);
const auto size = max(n.size(), m.size());
n.resize(size);
m.resize(size);
vector<int> sums(size);
transform(cbegin(n), cend(n), cbegin(m), begin(sums), plus<>{});
copy(cbegin(sums), cend(sums), ostream_iterator<int>{cout, ", "});
cout << endl;
}

Finding multiples of integers quickly

I've written out this particular code in C++ to try and find out all the multiples of the integers 3 & 5 below 1000 by using a while loop and then storing it in integer arrays. I also want to print each of those multiples out. But every time I debug this program, it endlessly prints out '0'. I just don't understand. Can someone please explain how to correct this code and why that unusual output occurs?
#include <iostream>
using namespace std;
int main()
{
const int three_limit = 334;
const int five_limit = 200;
int threeArray[three_limit] = {0};
int fiveArray[five_limit] = {0};
int i = 1, j = 1;
while (i < three_limit)
{
int multiples = 3*i;
multiples = threeArray[i - 1];
cout << threeArray[i - 1] << endl;
i++;
}
while (j < five_limit)
{
int multiples = 5*i;
multiples = fiveArray[j - 1];
cout << fiveArray[j - 1] << endl;
j++;
}
char response;
cin >> response;
return 0;
}
Your output will have duplicates when the number contains multiples of 3 and 5, e.g. 15, 30.
Some of the suggestions use multiplication or mod (%) which are quite slow, but there's a much faster solution using a binary array that will also help you avoid the duplication problem. Something like:
int main() {
bool nums[1001];
for(int i = 1; i < 1001; ++i)
nums[i] = 0;
for(int i = 3; i < 1001; i += 3)
nums[i] = 1;
for(int i = 5; i < 1001; i += 5)
nums[i] = 1;
for(int i = 1; i < 1001; ++i)
if(nums[i])
cout << i << endl;
}
It should be
threeArray[i - 1] = multiples;
instead of
multiples = threeArray[i - 1];
See the following code, to generate multiples of 5
#include<stdio.h>
int main(){
int max=1000;
int i=1,result=0;
while(result!=max && i!=200)
{
result=5*i; // change the 5 by 3 for multiples of 3
printf("\n %d",result);
i++;
}
}
I guess this
multiples = threeArray[i - 1];
should really be
threeArray[i - 1] = multiples;
Try debugging it again and watch multiples while executing this line.
multiples = threeArray[i - 1];
You're overwriting the local int with the (empty) contents of the array - you have your assignment the wrong way around.
You never modify the values in your array. It should be something like this:
while (i < three_limit)
{
int multiples = 3*i;
threeArray[i-1] = multiples;
cout << threeArray[i - 1] << endl;
i++;
}