Acyclic undirected graph allocation problem - c++

We have an allocation problem: each node is a fuel source, and every edge contains a number of evenly spaced out lamps (think of them as being 1 m apart from each other). Each fuel source can power lamps that are on the immediate edges around it (it cannot fuel lamps through other nodes). A fuel source also has a radius in which it fuels lamps around it - depending on the radius (in meters) we can calculate the amount of fuel a give fuel source provides - example: a fuel source with a radius of 2 can fuel all the lamps within its radius and, in total, uses up 2 liters of fuel (fuel usage is a function of the radius).
Note that two nodes have only one path between each other (meaning that that the number of edges is equal to the number of nodes - 1).
The goal is to calculate the optimal radii of the fuel sources so that we minimize the fuel usage while fueling all the lamps.
Here is an example graph
The solution to this graph looks like this. The red ellipsoids are supposed to visualize the radii of the fuel sources, and below is a table of the relevant values:
Node, fuel source
Radius, fuel consumption
0
1
1
2
2
0
3
2
4
0
5
0
After we add up all the fuel amounts, we get the result: 5.
The input for the above task looks like this:
6 // 6 nodes (numVertices)
0 1 3 // Node 0 with an edge containing 3 nodes going to node 3 (src dest lights)
1 2 1 // ...
2 3 2
1 4 2
1 5 2
So far I've tried loading up my edges like this (note that this solution is quite cursed, especially with my use of pointers):
struct light {
int count;
};
struct node {
int d;
light* l;
};
std::vector<node*>* tree;
int numVertices;
// Do this for all values in the input
void AddEdge(int src, int dest, int lights) {
light* l = new light{ lights };
tree[src].push_back(new node{ dest, l });
tree[dest].push_back(new node{ src, l });
}
And then I solved the graph by using a greedy algorithm to 'remove' as many lamps per step as possible:
void Solve() {
int fuel = 0;
while (true) {
int maxNode = 0;
int maxNodeLights = 0;
for (int A = 0; A < numVertices; A++)
{
int lightsOnNode = 0;
for (node* B : tree[A])
{
lightsOnNode += B->l->count;
}
if (lightsOnNode > maxNodeLights) {
maxNodeLights = lightsOnNode;
maxNode = A;
}
}
if (maxNodeLights > 0) {
bool addedRange = false;
for (node* B : tree[maxNode])
{
if (B->l->count > 0) {
B->l->count--;
addedRange = true;
}
}
if (addedRange) {
fuel++;
}
}
else {
break;
}
}
std::cout << fuel << '\n';
}
If we were to parse the input string from the example case it would look like this:
numVertices = 6;
AddEdge(0, 1, 3);
AddEdge(1, 2, 1);
AddEdge(2, 3, 2);
AddEdge(1, 4, 2);
AddEdge(1, 5, 2);
Solve();
This works for simple graphs like the one above, but it fails by a small margin once a more complex graph is introduced, since the greedy algorithm doesn't look ahead if there is a better option a couple steps in the future.
A long test case can be found here. The fuel amount consumed by this graph is 77481.
New, failing test cases:
1 0 4
2 1 1
3 2 4
4 3 1
5 1 2
6 1 1
7 2 2
8 3 2
9 1 1
10 1 3
11 5 1
12 0 2
13 10 4
14 3 3
15 5 4
(Output: 16. Correct output: 17)
1 0 2
2 1 3
3 2 2
4 1 4
5 4 3
6 3 2
7 5 3
8 3 4
(Output: 10. Correct output: 11)
1 0 4
2 0 3
3 0 4
4 3 3
5 2 2
6 3 1
7 2 1
8 3 2
9 3 2
10 2 1
11 9 1
12 4 2
13 5 2
14 8 2
15 9 1
16 14 2
17 3 3
18 3 4
(Output: 15. Correct output: 16)

Algorithm pseudocode:
WHILE lamps remain unfueled
LOOP over sources
IF source has exactly one edge with unfueled lamps
SET fuel source to source at other end of unfueled edge
INCREMENT radius of fuel source with unfueled edge lamp count
LOOP over edges on fuel source
IF edge fueled lamp count from fuel sourve < fuel source radius
SET edge fueled lamp count from fuel source to fuel source radius
C++ code for this is at https://github.com/JamesBremner/LampLighter.
Sample output
Input
0 1 1
1 2 1
2 3 1
3 4 1
0 5 1
5 6 1
6 7 1
7 8 1
0 9 1
9 10 1
10 11 1
11 12 1
Source radii
0 r=0
1 r=1
2 r=0
3 r=1
4 r=0
5 r=1
6 r=0
7 r=1
8 r=0
9 r=1
10 r=0
11 r=1
12 r=0
Total fuel 6
Handling different numbers of lamps on each edge
0 1 3
1 2 1
0 5 3
5 6 1
Source radius
0 r=2
1 r=1
2 r=0
5 r=1
6 r=0
Total fuel 4
Another test
lamp ..\test\data11_19_2.txt
Output:
1 0 2
2 1 3
3 2 2
4 1 4
5 4 3
6 3 2
7 5 3
8 3 4
Source radius
1 r=3
0 r=0
2 r=0
3 r=4
4 r=0
5 r=3
6 r=0
7 r=0
8 r=0
Total fuel 10
Acknowledgement: This algorithm is based on an insight from MarkB who suggested that fueling should begin at leaf nodes and work "downwards"

Related

Vector behaving wierdly

I was trying to find super lucky numbers that is numbers that contain only 4 and 7 as their digit (lucky number) and the number of 4's and 7's must be same (super lucky number). I used recursion to find the lucky numbers and stored them in vector. Then i looped over all lucky elements to check if it is super lucky. But while doing this when i was copying each vector element to another variable for checking its digits, the copy is not working properly. I don't know why it is copying wrong number .
The code goes like:
#include<iostream>
#include<vector>
using namespace std;
vector<long long int> v;
void comb(long long int x){
v.push_back(x);
if(x<10000000){
comb(x*10+4);
comb(x*10+7);
}
}
int main(){
int n,f,s;
long long int n1;
cin>>n;
comb(0);
for(long long int i=1;i<v.size();i++){
n1=v[i]; //here i copied the element to variable
f=0;
s=0;
cout<<n1<<" "; // But when i checked the value of variable it is not equal to element
while(n1>0LL){
if(n1%10LL==4LL){
f++;
}else s++;
n1/=10LL;
}
if(f!=s){
v.erase(v.begin()+i);
}
cout<<v[i]<<" "<<f<<" "<<s<<'\n';
}
return 0;
}
The output goes like:
4 44 1 0 // n1 v[i] f s
444 4444 3 0
44444 444444 5 0
4444444 44444444 7 0
44444447 4444447 7 1
44444474 44444477 7 1
444447 4444474 5 1
44444744 44444747 7 1
4444477 44444774 5 2
44444777 44447 5 3
444474 4444744 5 1
44447444 44447447 7 1
4444747 44447474 5 2
44447477 444477 5 3
4444774 44447744 5 2
44447747 4444777 5 3
44447774 44447777 5 3
4447 44474 3 1
444744 4447444 5 1
44474444 44474447 7 1
4447447 44474474 5 2
44474477 444747 5 3
4447474 44474744 5 2
44474747 4447477 5 3
44474774 44474777 5 3
44477 444774 3 2
4447744 44477444 5 2
44477447 4447747 5 3
44477474 44477477 5 3
444777 444777 3 3
4447774 44477744 4 3
44477747 44477747 4 4
4447777 44477774 3 4
44477777 447 3 5
4474 44744 3 1
447444 4474444 5 1
44744444 44744447 7 1
4474447 44744474 5 2
44744477 447447 5 3
4474474 44744744 5 2
44744747 4474477 5 3
44744774 44744777 5 3
44747 447474 3 2
4474744 44747444 5 2
44747447 4474747 5 3
44747474 44747477 5 3
447477 447477 3 3
4474774 44747744 4 3
44747747 44747747 4 4
4474777 44747774 3 4
44747777 4477 3 5
44774 447744 3 2
4477444 44774444 5 2
44774447 4477447 5 3
44774474 44774477 5 3
447747 447747 3 3
4477474 44774744 4 3
44774747 44774747 4 4
4477477 44774774 3 4
44774777 44777 3 5
447774 447774 3 3
4477744 44777444 4 3
44777447 44777447 4 4
4477747 44777474 3 4
44777477 447777 3 5
4477774 44777744 3 4
44777747 4477777 3 5
44777774 44777777 3 5
47 47 1 1
474 4744 2 1
47444 474444 4 1
4744444 47444444 6 1
47444447 4744447 6 2
47444474 47444477 6 2
474447 4744474 4 2
47444744 47444747 6 2
4744477 47444774 4 3
47444777 47444777 4 4
47447 474474 3 2
4744744 47447444 5 2
47447447 4744747 5 3
47447474 47447477 5 3
474477 474477 3 3
4744774 47447744 4 3
47447747 47447747 4 4
4744777 47447774 3 4
47447777 4747 3 5
47474 474744 3 2
4747444 47474444 5 2
47474447 4747447 5 3
47474474 47474477 5 3
474747 474747 3 3
4747474 47474744 4 3
47474747 47474747 4 4
4747477 47474774 3 4
47474777 47477 3 5
474774 474774 3 3
4747744 47477444 4 3
47477447 47477447 4 4
4747747 47477474 3 4
47477477 474777 3 5
4747774 47477744 3 4
47477747 4747777 3 5
47477774 47477777 3 5
477 4774 1 2
47744 477444 3 2
4774444 47744444 5 2
47744447 4774447 5 3
47744474 47744477 5 3
477447 477447 3 3
4774474 47744744 4 3
47744747 47744747 4 4
4774477 47744774 3 4
47744777 47747 3 5
..........................................
Why is this behaving like this?
You print n1 whatever value it is. Then if it isn't super lucky number, you remove v[i] which is same as n1 then print new v[i], which is the next value of original v[i].

My selection sort replaces some numbers in the array with 0

This is the complete code that I wrote:
( [numsin the function] and [arrin main] is the array that needs to be sorted, sizeis the amount of numbers in the array, minis the smallest number in the unsorted part)
#include <iostream>
#include <vector>
using namespace std;
void sort(vector <int> &nums, int size){
int min = 0;
for(int i=0;i<size;i++){
min = i;
for(int j=i+1;j<size;j++){
if(nums[j]<nums[min]){
min = j; //comparing
}
}
nums[i] = nums[min] + nums[i]; //swaping
nums[min] = nums[i] - nums[min];
nums[i] = nums[i] - nums[min];
}
}
int main(){
cout<<"\nEnter Numbers:\n";
vector <int> arr;
int num;
while(cin>>num){
arr.push_back(num);
}
sort(arr,arr.size());
cout<<"\nSorted:\n";
for(int i=0;i<arr.size();i++){
cout<<arr[i]<<" ";
}
}
I'm writing a code that simply sorts the given array. But after trying to debug and find solutions online, I can't figure out which part is wrong. These are some examples of my results:
Enter Numbers:
9 8 7 6 1 2 3 4 5 ^Z
Sorted:
1 2 3 4 5 6 0 0 0
Enter Numbers:
6 4 8 7 2 3 5 ^Z
Sorted:
2 3 4 5 0 7 0
Enter Numbers:
9 8 7 6 5 4 3 2 1 ^Z
Sorted:
1 2 3 4 0 0 0 0 0
This is the result when I added a for loop under the swapping part to show what every round has done to the array:
Enter Numbers:
9 8 7 6 1 2 3 4 5 ^Z
1 8 7 6 9 2 3 4 5
1 2 7 6 9 8 3 4 5
1 2 3 6 9 8 7 4 5
1 2 3 4 9 8 7 6 5
1 2 3 4 5 8 7 6 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 0 8 9
1 2 3 4 5 6 0 0 9
1 2 3 4 5 6 0 0 0
Sorted:
1 2 3 4 5 6 0 0 0
Enter Numbers:
6 4 8 7 2 3 5 ^Z
2 4 8 7 6 3 5
2 3 8 7 6 4 5
2 3 4 7 6 8 5
2 3 4 5 6 8 7
2 3 4 5 0 8 7
2 3 4 5 0 7 8
2 3 4 5 0 7 0
Sorted:
2 3 4 5 0 7 0
9 8 7 6 5 4 3 2 1 ^Z
1 8 7 6 5 4 3 2 9
1 2 7 6 5 4 3 8 9
1 2 3 6 5 4 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 0 6 7 8 9
1 2 3 4 0 0 7 8 9
1 2 3 4 0 0 0 8 9
1 2 3 4 0 0 0 0 9
1 2 3 4 0 0 0 0 0
Sorted:
1 2 3 4 0 0 0 0 0
Please help, thanks.
Your swapping logic doesn't handle the case where the smallest remaining element is the first unsorted element (i.e., i == min). Consider what each line does in this case:
nums[i] = nums[min] + nums[i]; //nums[i] will be doubled
nums[min] = nums[i] - nums[min]; // nums[min] is subtracted from itself, making it 0
nums[i] = nums[i] - nums[min]; // nums[i] is subtracted from itself gain, but 0-0 is still 0
The goal of avoiding a temporary isn't bad by itself, but you do have this nasty edge case. You'd either have to detect the edge case or just bite the bullet and deal with a temporary. You could also call std::swap, but that likely uses a temporary as well.
The advantage to using a temporary or std::swap is that this code would be easier to make generic for other types (especially via std::swap). In addition, std::swap can be specialized for types to avoid temporaries if possible, and if this is actually a bottleneck.

Codechef is rejecting my solution

I am newbie on codechef and i was trying to solve the following question however my code runs fine on my machine, i also tested it with some cases.
Question is as follows :-
In Byteland it is always the military officer's main worry to order his soldiers on parade correctly. Luckily, ordering soldiers is not really such a problem. If a platoon consists of n men, all of them have different rank (from 1 - lowest to n - highest) and on parade they should be lined up from left to right in increasing order of rank.
Sounds simple, doesn't it? Well, Sgt Johnny thought the same, until one day he was faced with a new command. He soon discovered that his elite commandos preferred to do the fighting, and leave the thinking to their superiors. So, when at the first rollcall the soldiers lined up in fairly random order it was not because of their lack of discipline, but simply because they couldn't work out how to form a line in correct order of ranks. Sgt Johnny was not at all amused, particularly as he soon found that none of the soldiers even remembered his own rank. Over the years of service every soldier had only learned which of the other soldiers were his superiors. But Sgt Johnny was not a man to give up easily when faced with a true military challenge. After a moment's thought a solution of brilliant simplicity struck him and he issued the following order: "men, starting from the left, one by one, do: (step forward; go left until there is no superior to the left of you; get back in line).". This did indeed get the men sorted in a few minutes. The problem was solved... for the time being.
The next day, the soldiers came in exactly the same order as the day before, and had to be rearranged using the same method. History repeated. After some weeks, Sgt Johnny managed to force each of his soldiers to remember how many men he passed when going left, and thus make the sorting process even faster.
If you know how many positions each man has to walk to the left, can you try to find out what order of ranks the soldiers initially line up in?
Input
The first line of input contains an integer t<=50, the number of test cases. It is followed by t test cases, each consisting of 2 lines. The first line contains a single integer n (1<=n<=200000). The second line contains n space separated integers wi, denoting how far the i-th soldier in line must walk to the left when applying Sgt Johnny's algorithm.
Output
For each test case, output a single line consisting of n space separated integers - the ranks of the soldiers, given from left to right in their initial arrangement.
Example
Input:
2
3
0 1 0
5
0 1 2 0 1
Output:
2 1 3
3 2 1 5 4
Warning: large Input/Output data, be careful with certain languages
#include <iostream>
#include <string.h>
using namespace std;
int main ()
{
int t,n;
cin >> t;
while(t>0){
cin >> n;
int array[n+1];
int stepsmoved,i;
for(i = 1; i <= n; i++){
array[i] = i;
}
for(i = 1; i <=n; i++){
cin >> stepsmoved;
if(stepsmoved == 0){}
else{
int x;
x = array[i];
for (int j = i; j> i- stepsmoved; j--){
array[j] = array[j-1];
}
array[i-stepsmoved] = x;
}
}
for(i = 1; i <= n; i++){
cout<<array[i]<<" ";
}
cout<<endl;
t--;
}
return 0;
}
So is there something logically or syntactically wrong?
The order of 'unwinding' the sorting is relevant.
Here is the code that demonstrates the statement above (the ranks are 1-based, the 1 - is highest, 10 - is lowest, array indices are 0-based):
#include <stdio.h>
void dump(int *a) {
int i;
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
}
int main() {
int array[10] = {0}, steps[10] = {0};
int i,j;
srand(0);
// Assign ranks in random order
for (i = 0; i < 10;) {
j = rand() % 10;
if (!array[j])
array[j] = ++i;
}
dump(array);
// Sort according to the Sgt Johnny's initial idea
for (i = 1; i < 10; i++) {
for (j = 0; array[j] < array[i]; j++);
if (j < i) {
int k, temp = array[i];
for (k = i; k > j; k--) {
array[k] = array[k-1];
steps[temp-1]++;
}
array[j] = temp;
dump(array);
}
}
printf("Steps:\n");
dump(steps);
printf("\n");
// reconstruct the origina order
#if 1
for (i = 10-1; i >= 0; i--)
#else
for (i = 0; i < 10; i++)
#endif
{
int s = steps[array[i]-1];
for (j = i; s; s--, j++) {
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
dump(array);
}
}
If the reconstruction is done in reverse order, then we get a sequence that matches original:
8 7 5 1 10 4 2 3 9 6
7 8 5 1 10 4 2 3 9 6
5 7 8 1 10 4 2 3 9 6
1 5 7 8 10 4 2 3 9 6
1 4 5 7 8 10 2 3 9 6
1 2 4 5 7 8 10 3 9 6
1 2 3 4 5 7 8 10 9 6
1 2 3 4 5 7 8 9 10 6
1 2 3 4 5 6 7 8 9 10
Steps:
3 5 5 4 2 4 1 0 1 0
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 10 9
1 2 3 4 5 6 7 8 10 9
1 2 3 4 5 6 8 7 10 9
1 2 3 4 5 8 7 10 9 6
1 2 3 4 8 7 5 10 9 6
1 2 3 8 7 5 10 4 9 6
1 2 8 7 5 10 4 3 9 6
1 8 7 5 10 4 2 3 9 6
8 7 5 1 10 4 2 3 9 6
Otherwise, the reconstructed order does not match the original:
8 7 5 1 10 4 2 3 9 6
7 8 5 1 10 4 2 3 9 6
5 7 8 1 10 4 2 3 9 6
1 5 7 8 10 4 2 3 9 6
1 4 5 7 8 10 2 3 9 6
1 2 4 5 7 8 10 3 9 6
1 2 3 4 5 7 8 10 9 6
1 2 3 4 5 7 8 9 10 6
1 2 3 4 5 6 7 8 9 10
Steps:
3 5 5 4 2 4 1 0 1 0
2 3 4 1 5 6 7 8 9 10
2 4 1 5 6 7 3 8 9 10
2 4 5 6 7 1 3 8 9 10
2 4 5 7 1 3 8 6 9 10
2 4 5 7 3 8 6 1 9 10
2 4 5 7 3 8 6 1 9 10
2 4 5 7 3 8 1 9 10 0
2 4 5 7 3 8 1 10 9 0
2 4 5 7 3 8 1 10 0 9
2 4 5 7 3 8 1 10 0 6

abnormality in the output of my code

I'm trying to read an array in c++, filled with values from 0 to 5, For an unimportant reason, I need to count how many numbers 1, numbers 2, numbers 3, numbers 4 and numbers 5 do stand on the 'iii*DAYS'th position, so when iii = 0 and DAYS is 5, I need to know how many numbers 1, numbers 2, numbers 3, numbers 4 and numbers 5 are located on the 0th, 4th, 9th, 14th position. The code I posted does this quite well, but sometimes, gives a very big unlogical value, -36589245 or 99653256, can somebody tell me why this happens ( it does happen +- one in a hunderd times )
DAYS = 28
NURSES = 33
SHIFTS =5
int calculate_penalty_coverage_offspring(int offspring[NURSES*DAYS])
{
int temporary[DAYS];
int count[DAYS][SHIFTS];
penalty_score_offspring_coverage =0;
for (int ii = 0; ii<DAYS; ii++)
{
int een = 0;
int twee = 0;
int drie = 0;
int vier = 0;
int vijf = 0;
for (int iii = 0; iii<NURSES; iii++)
{
temporary[iii] = offspring[(ii+(iii*DAYS))];
}
for(int a = 0 ; a<DAYS ; a++)
{
if(temporary[a]== 1)
{
een++;
count[ii][0] = een;
}
else if(temporary[a] == 2)
{
twee++;
count[ii][1] = twee;
}
else if(temporary[a]== 3)
{
drie++;
count[ii][2] = drie;
}
else if(temporary[a]== 4)
{
vier++;
count[ii][3] = vier;
}
else if(temporary[a] == 5)
{
vijf++;
count[ii][4] = vijf;
}
}
}
for(int ii = 0; ii<DAYS ; ii++)
{
for (int iii =0 ; iii<SHIFTS ; iii++)
{
cout << count[ii][iii] << '\t';
}
cout << '\n';
}
this is the exeptional output where I talked about, as you can see, there is an onlogical value in the output of -31427696 ... I can't see why the function is working good, except for this one time.
1 2 2 4 4
5 2 2 9 5
9 6 3 5 2
8 3 4 3 8
9 3 3 4 6
5 5 6 8 1
6 8 2 2 5
3 5 8 -31427696 7
5 5 2 5 8
5 7 8 2 3
2 7 1 2 10
5 6 3 5 5
4 4 4 6 7
7 4 6 4 6
6 5 6 4 3
5 3 7 4 6
5 5 6 1 7
5 5 1 6 2
4 6 6 4 5
3 3 4 5 9
6 6 5 4 4
5 5 4 4 5
8 4 4 5 3
5 5 4 7 5
4 8 6 3 3
9 1 5 7 3
3 7 5 2 5
2 6 5 7 5
First you say
int temporary[DAYS];
Where
DAYS = 28
Then you do:
for (int iii = 0; iii<NURSES; iii++)
{
temporary[iii] = offspring[(ii+(iii*DAYS))];
}
Where
NURSES = 33
You're trying to access indices that are out of bounds in temporary.
EDIT: Following our discussion in the comments,
You're additionally not initializing your arrays, specifically count:
int count[DAYS][SHIFTS];
Which you then conditionally fill in (partially) later:
if(temporary[a]== 1)
{
een++;
count[ii][0] = een;
}
// ...
Accesses to count afterwards to indices that were not assigned to will result in the garbage numbers you're seeing. You should probably just default the matrix to all zeros like so:
int count[DAYS][SHIFTS] = {0};

Mapping the subdivision of an matrix to a vector

I am trying to map the subdivision of a matrix to an array.
By subdivision of a matrix I mean a box like the 3x3 boxes in a 9x9 sudoku matrix.
To do so I use :
grid[x][y] = box[x/3 + (y/3)*3];
But it does not work, any sugesstion on a solution and an explanation of why it does not work ?
EDIT:
I know how to map a vector to a matrix.
I want to map a vector to a portion of a square matrix like just like in the sudoku game.
EDIT2:
Bassicaly what I want is to be able to map a box number to a tuple ,
for example with 3x3 boxes and a 9x9 matrix
(0,0) => 1
(0,1) => 1
(8,8) => 9
Updated Answer to Edit2:
If you want a mapping like:
1 2 3
4 5 6
7 8 9
then your original code is almost want you want (just add 1):
for (int y = 0; y < 9; ++y)
{
for (int x = 0; x < 9; ++x)
{
int index = x/3 + (y/3) * 3 + 1;
printf("%d ", index);
}
printf("\n");
}
Which outputs:
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
7 7 7 8 8 8 9 9 9
7 7 7 8 8 8 9 9 9
7 7 7 8 8 8 9 9 9