using
System;
using
System.Collections.Generic;
class
Item
{
public
float
Weight {
get
;
set
; }
public
int
Value {
get
;
set
; }
public
int
Index {
get
;
set
; }
public
Item(
int
value,
float
weight,
int
index)
{
Value = value;
Weight = weight;
Index = index;
}
}
class
Node
{
public
float
UpperBound {
get
;
set
; }
public
float
LowerBound {
get
;
set
; }
public
int
Level {
get
;
set
; }
public
bool
Flag {
get
;
set
; }
public
float
TotalValue {
get
;
set
; }
public
float
TotalWeight {
get
;
set
; }
public
Node() { }
public
Node(Node copy)
{
TotalValue = copy.TotalValue;
TotalWeight = copy.TotalWeight;
UpperBound = copy.UpperBound;
LowerBound = copy.LowerBound;
Level = copy.Level;
Flag = copy.Flag;
}
}
class
SortByC : IComparer<Node>
{
public
int
Compare(Node a, Node b)
{
return
a.LowerBound.CompareTo(b.LowerBound);
}
}
class
SortByRatio : IComparer<Item>
{
public
int
Compare(Item a, Item b)
{
return
((
float
)a.Value / a.Weight).CompareTo((
float
)b.Value / b.Weight);
}
}
class
Program
{
static
void
Assign(Node a,
float
ub,
float
lb,
int
level,
bool
flag,
float
tv,
float
tw)
{
a.UpperBound = ub;
a.LowerBound = lb;
a.Level = level;
a.Flag = flag;
a.TotalValue = tv;
a.TotalWeight = tw;
}
static
float
UpperBound(
float
tv,
float
tw,
int
idx, Item[] arr,
int
size,
float
capacity)
{
float
value = tv;
float
weight = tw;
for
(
int
i = idx; i < size; i++)
{
if
(weight + arr[i].Weight <= capacity)
{
weight += arr[i].Weight;
value -= arr[i].Value;
}
else
{
value -= ((capacity - weight) / arr[i].Weight) * arr[i].Value;
break
;
}
}
return
value;
}
static
float
LowerBound(
float
tv,
float
tw,
int
idx, Item[] arr,
int
size,
float
capacity)
{
float
value = tv;
float
weight = tw;
for
(
int
i = idx; i < size; i++)
{
if
(weight + arr[i].Weight <= capacity)
{
weight += arr[i].Weight;
value -= arr[i].Value;
}
else
{
break
;
}
}
return
value;
}
static
void
Solve(Item[] arr,
int
size,
float
capacity)
{
Array.Sort(arr,
new
SortByRatio());
Node current =
new
Node();
Node left =
new
Node();
Node right =
new
Node();
current.TotalValue = current.TotalWeight = current.UpperBound = current.LowerBound = 0;
current.Level = 0;
current.Flag =
false
;
float
minLB = 0, finalLB =
float
.MaxValue;
current.TotalValue = current.TotalWeight = current.UpperBound = current.LowerBound = 0;
current.Level = 0;
current.Flag =
false
;
PriorityQueue<Node> pq =
new
PriorityQueue<Node>(
new
SortByC());
pq.Enqueue(current);
bool
[] currPath =
new
bool
[size];
bool
[] finalPath =
new
bool
[size];
while
(pq.Count > 0)
{
current = pq.Dequeue();
if
(current.UpperBound > minLB || current.UpperBound >= finalLB)
{
continue
;
}
if
(current.Level != 0)
currPath[current.Level - 1] = current.Flag;
if
(current.Level == size)
{
if
(current.LowerBound < finalLB)
{
for
(
int
i = 0; i < size; i++)
finalPath[arr[i].Index] = currPath[i];
finalLB = current.LowerBound;
}
continue
;
}
int
level = current.Level;
Assign(right, UpperBound(current.TotalValue, current.TotalWeight, level + 1, arr, size, capacity),
LowerBound(current.TotalValue, current.TotalWeight, level + 1, arr, size, capacity),
level + 1,
false
, current.TotalValue, current.TotalWeight);
if
(current.TotalWeight + arr[current.Level].Weight <= capacity)
{
left.UpperBound = UpperBound(current.TotalValue - arr[level].Value, current.TotalWeight + arr[level].Weight, level + 1, arr, size, capacity);
left.LowerBound = LowerBound(current.TotalValue - arr[level].Value, current.TotalWeight + arr[level].Weight, level + 1, arr, size, capacity);
Assign(left, left.UpperBound, left.LowerBound, level + 1,
true
, current.TotalValue - arr[level].Value, current.TotalWeight + arr[level].Weight);
}
else
{
left.UpperBound = left.LowerBound = 1;
}
minLB = Math.Min(minLB, left.LowerBound);
minLB = Math.Min(minLB, right.LowerBound);
if
(minLB >= left.UpperBound)
pq.Enqueue(left);
if
(minLB >= right.UpperBound)
pq.Enqueue(right);
}
Console.WriteLine(
"Items taken into the knapsack are"
);
for
(
int
i = 0; i < size; i++)
{
if
(finalPath[i])
Console.Write(
"1 "
);
else
Console.Write(
"0 "
);
}
Console.WriteLine($
"\nMaximum profit is {-finalLB}"
);
}
static
void
Main()
{
int
size = 4;
float
capacity = 15;
Item[] arr = {
new
Item(10, 2, 0),
new
Item(10, 4, 1),
new
Item(12, 6, 2),
new
Item(18, 9, 3) };
Solve(arr, size, capacity);
}
}
public
class
PriorityQueue<T>
{
private
List<T> list;
private
IComparer<T> comparer;
public
PriorityQueue(IComparer<T> comparer)
{
this
.list =
new
List<T>();
this
.comparer = comparer;
}
public
int
Count
{
get
{
return
list.Count; }
}
public
void
Enqueue(T item)
{
list.Add(item);
int
i = list.Count - 1;
while
(i > 0)
{
int
parent = (i - 1) / 2;
if
(comparer.Compare(list[i], list[parent]) >= 0)
break
;
Swap(i, parent);
i = parent;
}
}
public
T Dequeue()
{
int
count = list.Count;
if
(count == 0)
throw
new
InvalidOperationException(
"Queue is empty"
);
T root = list[0];
if
(count == 1)
{
list.RemoveAt(0);
}
else
{
list[0] = list[count - 1];
list.RemoveAt(count - 1);
Heapify(0);
}
return
root;
}
private
void
Heapify(
int
i)
{
int
leftChild, rightChild, smallestChild;
while
(
true
)
{
leftChild = 2 * i + 1;
rightChild = 2 * i + 2;
smallestChild = i;
if
(leftChild < list.Count && comparer.Compare(list[leftChild], list[smallestChild]) < 0)
smallestChild = leftChild;
if
(rightChild < list.Count && comparer.Compare(list[rightChild], list[smallestChild]) < 0)
smallestChild = rightChild;
if
(smallestChild == i)
break
;
Swap(i, smallestChild);
i = smallestChild;
}
}
private
void
Swap(
int
i,
int
j)
{
T temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}