Party schedule - classical knapsack - c++

The input is a available budget, number of parties, the ticket-price of each party and the amount of fun on the party. The task is to output the maximum possible fun with available budget and the budget used. If you can choose between two parties with the same fun, choose the cheaper one. (It is a SPOJ problem.)
I created two arrays:
m[i][j] is the maximum fun to get from all parties up to i with
budget j
p[i][j] minimum price to py to get max. fun from parties
up to i with budget j
Then, for each i up to #parties and for each j up to budget I calculated the value of m[i][j] and p[i][j] like this:
for(T i = 1; i <= parties; i++) {
for(T j = 0; j <= budget; j++) {
//We get more fun by attending party i
if(price[i] <= j && m[i-1][j-price[i]] + fun[i] > m[i-1][j]) {
m[i][j] = m[i-1][j-price[i]] + fun[i];
p[i][j] = p[i-1][j-price[i]] + price[i];
//We get same fun by attending i, but more cheaply
} else if(price[i] <= j && m[i-1][j-price[i]] + fun[i] == m[i-1][j] && p[i-1][j-price[i]] + price[i] < p[i-1][j]) {
m[i][j] = m[i-1][j-price[i]] + fun[i];
p[i][j] = p[i-1][j-price[i]] + price[i];
//We can't visit the party
} else {
m[i][j] = m[i-1][j];
p[i][j] = p[i-1][j];
}
}
}
For any test case I found (I may share some if needed), this algorithm outputs the same answer as the algorithms approved by the online judge. However, this one is not approved.
What is wrong with the algorithm?
Here is the complete program.

I checked your complete code without going through your logic, but there were some must-be-wrong points:
You decalred your price array inside function as price[parties], which only allows price[0..parties - 1], but you used up to price[parties], same as fun[];
The condition for your while is while(scanf("%u %u",&budget,&parties), budget != 0 && parties != 0), however budget can be 0 even in a valid input, so your program may terminate earlier than expected;
You declared your m[][] and p[][] inside function but didn't initialize it, so it would be filled up with rubbish values;
You print the answer using printf("%u %u"), but the problem requires a new line for each output, so here should be printf("%u %u\n").
After I changed these 4 "bugs" in your program, it gets accepted :) So your algorithm logic is approved, but some "irrelevant" things prevents you from getting accepted. Don't look down on these "details", they DO count!

Related

Minimum edit distance of two documents

I know how to get the minimum edit distance of two short strings like 'abcde' and 'abfde',but how to do the MED of two documents or essays with spaces , tabs , enters or even two codes?
For example:
text1:
The computer learns from a huge database of four million videos from volunteers and paid-for market
researchers in various emotional states and the algorithms are constantly updated and tested against real-world
scenarios.
The next stage is to integrate voice analysis and other measures of physical wellbeing such as heart rate and
hand gestures.
and
text2:A computer model has been developed that can predict what word you are thinking of. The model may help to
resolve questions about how the brain processes words and language, and might even lead to techniques for
decoding people’s thoughts.
Researchers led by Tom Mitchell of Carnegie Mellon University in Pittsburgh, Pennsylvania, 'trained' a computer
model to recognize the patterns of brain activity associated with 60 images, each of which represented a
different noun, such as 'celery' or 'aeroplane'.
This is the code I wrote of finding the MED of two strings within 20 characters.
`
int med_lev(char S[], char T[]) {
int dis_lev[20][20];
int n = strlen(S);
int m = strlen(T);
for (int i = 0; i <= n; i++) {
dis_lev[i][0] = i;
}
for (int j = 0; j <= m; j++) {
dis_lev[0][j] = j;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (S[i - 1] == T[j - 1]) {
dis_lev[i][j] = dis_lev[i - 1][j - 1];
}
else {
dis_lev[i][j] = min(dis_lev[i - 1][j - 1] + 2, min(dis_lev[i - 1][j] + 1, dis_lev[i][j - 1] + 1));
}
}
}
return dis_lev[n][m];
}
`
I've thought out a method that is delete all spaces , tabs , enters and put every word in a single string but the problem is the string might be too long. Is there a better way?

if statement inside of for loop not being executed

Writing a program to solve problem four of project euler: Find the largest palindrome made from the product of two 2-digit numbers. Heres my reprex:
#include <iostream>
int reverseNumber(int testNum)
{
int reversedNum, remainder = 0;
int temp = testNum;
while(temp != 0)
{
remainder = temp % 10;
reversedNum = reversedNum * 10 + remainder;
temp /= 10;
}
return reversedNum;
}
int main()
{
const int MIN = 100;
int numOne = 99;
int product = 0;
for(int numTwo = 10; numTwo < 100; numTwo++)
{
product = numOne * numTwo;
if (reverseNumber(product) == product)
{
int solution = product;
std::cout << solution << '\n';
return 0;
}
}
return 0;
}
My main thought process behind this is that the for loop will go through every number from 10 to 99 and multiply it by 99. My intended outcome is for it to print 9009 which is the largest palindrome with 2 factors of 2 digits. So what I think should happen here is the for loop will go from 10 to 99, and each loop it should go through the parameters of the if statement which reverses the number and sees if it equals itself.
I've made sure it wasn't a compiler issue, as this is recurring between different compilers. The reverseNumber() function returns the proper number every time I've tested it, so that shouldn't be the problem, however this problem only occurs when the function is involved in the logical comparison. By this I mean if that even I set it equal to a variable and put the variable in the if parameters, the issue still occurs. I'm pretty much stumped. I just hope it's not some silly mistake as I've been on this for a couple days now.
int reversedNum, remainder = 0;
You should be aware that this gives you (in an automatic variable context) a zero remainder but an arbitrary reversedNum. This is actually one of the reasons some development shops have the "one variable per declaration" rule.
In other words, it should probably be:
int reversedNum = 0, remainder;
or even:
int reversedNum = 0;
int remainder;
One other thing that often helps out is to limit the scope of variable to as small an area as possible, only bringing them into existence when needed. An example of that would be:
int reverseNumber(int testNum) {
int reversedNum = 0;
while (testNum != 0) {
int remainder = testNum % 10;
reversedNum = reversedNum * 10 + remainder;
testNum /= 10;
}
return reversedNum;
}
In fact, I'd probably go further and eliminate remainder altogether since you only use it once:
reversedNum = reversedNum * 10 + testNum % 10;
You'll notice I've gotten rid of temp there as well. There's little to gain by putting testNum into a temporary variable since it's already a copy of the original (as it was passed in by value).
And one other note, more to do with the problem rather than the code. You seem to be assuming that there is a palindrome formed that is a multiple of 99. That may be the case but a cautious programmer wouldn't rely on it - if you're allowed to assume things like that, you could just replace your entire program with:
print 9009
Hence you should probably check all possibilities.
You also get the first one you find which is not necessarily the highest one (for example, let's assume that 99 * 17 and 99 * 29 are both palindromic - you don't want the first one.
And, since you're checking all possibilities, you probably don't want to stop at the first one, even if the nested loops are decrementing instead of incrementing. That's because, if 99 * 3 and 97 * 97 are both palindromic, you want the highest, not the first.
So a better approach may be to start high and do an exhaustive search, while also ensuring you ignore the palindrome check of candidates that are smaller that your current maximum, something like (pseudo-code)
# Current highest palindrome.
high = -1
# Check in reverse order, to quickly get a relatively high one.
for num1 in 99 .. 0 inclusive:
# Only need to check num2 values <= num1: if there was a
# better palindrome at (num2 * num1), we would have
# already found in with (num1 * num2).
for num2 in num1 .. 0 inclusive:
mult = num1 * num2
# Don't waste time doing palindrome check if it's
# not greater than current maximum - we can't use
# it then anyway. Also, if we find one, it's the
# highest possible for THIS num1 value (since num2
# is decreasing), so we can exit the num2 loop
# right away.
if mult > high:
if mult == reversed(mult):
high = mult
break
if high >= 0:
print "Solution is ", high
else:
print "No solution"
In addition to properly initializing your variables, if you want the largest palindrome, you should switch the direction of your for loop -- like:
for(int numTwo = 100; numTwo > 10; numTwo--) {
...
}
or else you are just printing the first palindrome within your specified range

Sort Function Deleting portion of array, C

I have this very weird issue going on. The function you will see in a moment is supposed to ensure that all elements (chars) in a 2D array are at there utmost position, that is, there is no empty space above any of the characters. For instance a board could look like this:
1 X * * X ^
2 * X ^ *
3 o o * X ^
4 o ^ X X X
5 ^ * X * ^
1 2 3 4 5
And there is an issue at (2,1) because there is an empty space above a non empty space.
My function does the sorting correctly but it deletes any character in the bottom row that has an empty space above it. I cannot, for the life of me, figure out why. Here is my sort function.
int bb_float_one_step(BBoard board){
int i,j;
for (i = 0; i < board->rows; i++){
for (j = 0; j < board->cols; j++){
if (board->boardDim[i][j] == None && (board->boardDim[i + 1][j] != None && i + 1 <= board->rows)){
char tmp = board->boardDim[i + 1][j];
board->boardDim[i + 1][j] = board->boardDim[i][j];
board->boardDim[i][j] = tmp;
}
}
}
for (i = 0; i < board->rows; i++){
for (j = 0; j < board->cols; j++){
printf("%c",board->boardDim[i][j]);}printf("\n");}
}
Below Is a picture of the full sequence, The Program prints a board. The user is asked to select a region to 'pop.' A function then replaces all the characters that are connected with a blank space. Then in the last portion of the picture you can see how the characters are deleted. The board that doesn't have a border is there because I was using it to check if the characters actually were deleted or not.
Thank you in advanced for 1, reading this whole post, and 2, any help you can give.
Since you are comparing current row with next row you should use for(i = 0; i < board->rows-1; i++)
Then in your complex if statement, get rid of && i <= board->rows. That should have been a less-than anyway, not less-than-or-equals. You're going out of bounds and getting garbage in your array.
You are checking the row beyond the maximum number of rows.
(board->boardDim[i + 1][j] != None && i + 1 <= board->rows)
That memory is not guaranteed to be 0. If it is not 0, your function will swap it in. If it is not human readable, printf won't print anything for it thereby shifting the | to the left.

How to improve upon this?

There are n groups of friends staying in the queue in front of bus station. The i-th group consists of ai men. Also, there is a single bus that works on the route. The size of the bus is x, that is it can transport x men simultaneously.
When the bus comes (it always comes empty) to the bus station, several groups from the head of the queue goes into the bus. Of course, groups of friends don't want to split, so they go to the bus only if the bus can hold the whole group. In the other hand, none wants to lose his position, that is the order of groups never changes.
The question is: how to choose the size x of the bus in such a way that the bus can transport all the groups and everytime when the bus moves off the bus station there is no empty space in the bus (the total number of men inside equals to x)?
Input Format:
The first line contains the only integer n (1≤n≤10^5). The second line contains n space-separated integers a1,a2,…,an (1≤ai≤10^4).
Output Format:
Print all the possible sizes of the bus in the increasing order.
Sample:
8
1 2 1 1 1 2 1 3
Output:
3 4 6 12
I made this code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
int max=0,sum=0,i,n;
cin>>n;
int values[100000];
for ( i = 0; i < n; i++ )
{
cin>>values[i];
sum = sum + values[i];
if ( values[i] > max )
max = values[i];
}
int p = 0,j;
int count = 0;
vector<int> final;
for ( i = 0; i < n; i++ )
{
p = p + values[i];
j = 0;
if ( p >= max && sum%p == 0)
{
flag = 0;
while ( j < n )
{
garb = p;
while (garb!= 0)
{
garb = garb - values[j++];
if ( garb < 0 )
flag = 1;
}
}
if ( flag == 0 )
{
final.push_back(p);
count++;
}
}
}
sort(final.begin(),final.end());
for ( j = 0; j < count; j++ )
{
cout<<final[j]<<"\t";
}
return 0;
}
Edit: I did this in which basically, I am checking if the found divisor satisfies the condition, and if at any point of time, I get a negative integer on taking difference with the values, I mark it by using a flag. However, it seems to give me a seg fault now. Why?
I firstly, calculated the maximum value out of the all possible values, and then, I checked if its a divisor of the sum of the values. However, this approach doesn't work for the input as:
10
2 2 1 1 1 1 1 2 1 2
My output is
2 7 14
whereas the output should be
7 14
only.
Any other approach that I can go with?
Thanks!
I can think of the following simple solution (since your present concern is correctness and not time complexity):
Calculate the sum of all ai's (as you are already doing).
Calculate the maximum of all ai's (as you are already doing).
Find all the factors of sum that are > max(ai).
For each factor, iterate through the ai's and check whether the bus condition is satisfied.

avoiding repeats in numbers for a 3x3 grid C++

I'm trying to make a solver that checks the block to make sure that no number repeats. Unfortunately, I can not get the correct logic on this and I'm not sure what I am doing incorrectly. Here is what I've got:
not quite sure why this is not working. Here's my code.
bool sudoku :: check_if_non_repeat(int r, int c, int v) //where r=row, c=column, v=value
Any idea why this is not working? I'm just getting infinite loops
if (!(j = brow && k == bcol))
Check that j=.... should be ==
I'm not sure what you tried to do, but I would do it like this:
bool sudoku :: check_if_non_repeat(int r, int c, int v) //where r=row, c=column, v=value
{
int brow = r/3;
int bcol = c/3;
for (int j = brow * 3; j < (brow * 3 + 3); j++)
for (int k = bcol * 3; k < (bcol * 3 + 3); k++)
if (sudoku_array[j][k] == v)
return true;
return false;
}
EDIT:
As noted below, the if statement need to be more complicated:
if ( sudoku_array[j][k] == v
&& v != 0
&& !(j == r && k == c))
return true;
I'm about to tell you about a different approach to the problem. I made a full solver a long while ago, and it basically used the opposite approach.
For each field, I had a std::bitset<9> which told me which values were still possible in that field. Each insertion would then update the other fields in the same row, column and box to remove that possibility, recursively filling out subsequent fields when any one of the them had one option left.
If it then tried to fill a number which was no longer allowed, then the last input given was no longer a valid number for that spot. That was also a far more thorough check than you're doing here: you won't be checking if you close off the last possibility for another field in the same row/column/box, let alone others.
I never did a couple planned optimizations, but even without them it outperformed (too quick to notice) my friend's solver (>50 seconds). Mostly because he had code like yours.