考虑到玩家有五个位置,您的背包问题将是:-
Knpsk(W,N,PG,C,SF,PF,Util) = max(Knpsk(W-Cost[N],N-1,...)+Value[N],Knpsk(W,N-1,PG,C,SF,PF,Util),Knpsk(W-Cost[N],N-1,PG,C,SF,PF,Util-1)+Value[N])
if(Pos[N]=="PG") then Knpsk(W-Cost[N],N-1,....) = Knpsk(W-Cost[N],N-1,PG-1,....)
if(Pos[N]=="C") then Knpsk(W-Cost[N],N-1,....) = Knpsk(W-Cost[N],N-1,PG,C-1....)
so on...
PG,C,SF,PF,Util are current position capacities
W is current knapsack capacity
N number of items available
动态编程可以像以前使用 7-D 表一样使用,并且在您的情况下,位置的值很小,它会使算法减慢 16 倍,这对于 np 完全问题非常有用
以下是JAVA中的动态编程解决方案:
public class KnapsackSolver {
HashMap CostMatrix;
// Maximum capacities for positions
int posCapacity[] = {2,1,2,2,2};
// Total positions
String[] positions = {"PG","C","SF","PF","util"};
ArrayList playerSet = new ArrayList<player>();
public ArrayList solutionSet;
public int bestCost;
class player {
int value;
int cost;
int pos;
String name;
public player(int value,int cost,int pos,String name) {
this.value = value;
this.cost = cost;
this.pos = pos;
this.name = name;
}
public String toString() {
return("'"+name+"'"+", "+value+", "+cost+", "+positions[pos]);
}
}
// Used to add player to list of available players
void additem(String name,int cost,int value,String pos) {
int i;
for(i=0;i<positions.length;i++) {
if(pos.equals(positions[i]))
break;
}
playerSet.add(new player(value,cost,i,name));
}
// Converts subproblem data to string for hashing
public String encode(int Capacity,int Totalitems,int[] positions) {
String Data = Capacity+","+Totalitems;
for(int i=0;i<positions.length;i++) {
Data = Data + "," + positions[i];
}
return(Data);
}
// Check if subproblem is in hash tables
int isDone(int capacity,int players,int[] positions) {
String k = encode(capacity,players,positions);
if(CostMatrix.containsKey(k)) {
//System.out.println("Key found: "+k+" "+(Integer)CostMatrix.get(k));
return((Integer)CostMatrix.get(k));
}
return(-1);
}
// Adds subproblem added hash table
void addEncode(int capacity,int players,int[] positions,int value) {
String k = encode(capacity,players,positions);
CostMatrix.put(k, value);
}
boolean checkvalid(int capacity,int players) {
return(!(capacity<1||players<0));
}
// Solve the Knapsack recursively with Hash look up
int solve(int capacity,int players,int[] posCapacity) {
// Check if sub problem is valid
if(checkvalid(capacity,players)) {
//System.out.println("Processing: "+encode(capacity,players,posCapacity));
player current = (player)playerSet.get(players);
int sum1 = 0,sum2 = 0,sum3 = 0;
int temp = isDone(capacity,players-1,posCapacity);
// Donot add player
if(temp>-1) {
sum1 = temp;
}
else sum1 = solve(capacity,players-1,posCapacity);
//check if current player can be added to knapsack
if(capacity>=current.cost) {
posCapacity[posCapacity.length-1]--;
temp = isDone(capacity-current.cost,players-1,posCapacity);
posCapacity[posCapacity.length-1]++;
// Add player to util
if(posCapacity[posCapacity.length-1]>0) {
if(temp>-1) {
sum2 = temp+current.value;
}
else {
posCapacity[posCapacity.length-1]--;
sum2 = solve(capacity-current.cost,players-1,posCapacity)+current.value;
posCapacity[posCapacity.length-1]++;
}
}
// Add player at its position
int i = current.pos;
if(posCapacity[i]>0) {
posCapacity[i]--;
temp = isDone(capacity-current.cost,players-1,posCapacity);
posCapacity[i]++;
if(temp>-1) {
sum3 = temp+current.value;
}
else {
posCapacity[i]--;
sum3 = solve(capacity-current.cost,players-1,posCapacity)+current.value;
posCapacity[i]++;
}
}
}
//System.out.println(sum1+ " "+ sum2+ " " + sum3 );
// Evaluate the maximum of all subproblem
int res = Math.max(Math.max(sum1,sum2), sum3);
//add current solution to Hash table
addEncode(capacity, players, posCapacity,res);
//System.out.println("Encoding: "+encode(capacity,players,posCapacity)+" Cost: "+res);
return(res);
}
return(0);
}
void getSolution(int capacity,int players,int[] posCapacity) {
if(players>=0) {
player curr = (player)playerSet.get(players);
int bestcost = isDone(capacity,players,posCapacity);
int sum1 = 0,sum2 = 0,sum3 = 0;
//System.out.println(encode(capacity,players-1,posCapacity)+" "+bestcost);
sum1 = isDone(capacity,players-1,posCapacity);
posCapacity[posCapacity.length-1]--;
sum2 = isDone(capacity-curr.cost,players-1,posCapacity) + curr.value;
posCapacity[posCapacity.length-1]++;
posCapacity[curr.pos]--;
sum3 = isDone(capacity-curr.cost,players-1,posCapacity) + curr.value;
posCapacity[curr.pos]++;
if(bestcost==0)
return;
// Check if player is not added
if(sum1==bestcost) {
getSolution(capacity,players-1,posCapacity);
}
// Check if player is added to util
else if(sum2==bestcost) {
solutionSet.add(curr);
//System.out.println(positions[posCapacity.length-1]+" added");
posCapacity[posCapacity.length-1]--;
getSolution(capacity-curr.cost,players-1,posCapacity);
posCapacity[posCapacity.length-1]++;
}
else {
solutionSet.add(curr);
//System.out.println(positions[curr.pos]+" added");
posCapacity[curr.pos]--;
getSolution(capacity-curr.cost,players-1,posCapacity);
posCapacity[curr.pos]++;
}
}
}
void getOptSet(int capacity) {
CostMatrix = new HashMap<String,Integer>();
bestCost = solve(capacity,playerSet.size()-1,posCapacity);
solutionSet = new ArrayList<player>();
getSolution(capacity, playerSet.size()-1, posCapacity);
}
public static void main(String[] args) {
KnapsackSolver ks = new KnapsackSolver();
ks.additem("david lee", 8000, 30, "PG");
ks.additem("kevin love", 12000, 50, "C");
ks.additem("kemba walker", 7300, 10, "SF");
ks.additem("jrue holiday", 12300, 30, "PF");
ks.additem("stephen curry", 10300, 80, "PG");
ks.additem("lebron james", 5300, 90, "PG");
ks.additem("kevin durant", 2300, 30, "C");
ks.additem("russell westbrook", 9300, 30, "SF");
ks.additem("kevin martin", 8300, 15, "PF");
ks.additem("steve nash", 4300, 15, "C");
ks.additem("kyle lowry", 6300, 20, "PG");
ks.additem("monta ellis", 8300, 30, "C");
ks.additem("dirk nowitzki", 7300, 25, "SF");
ks.additem("david lee", 9500, 35, "PF");
ks.additem("klay thompson", 6800, 28,"PG");
//System.out.println("Items added...");
// System.out.println(ks.playerSet);
int maxCost = 30000;
ks.getOptSet(maxCost);
System.out.println("Best Value: "+ks.bestCost);
System.out.println("Solution Set: "+ks.solutionSet);
}
}
注意:如果添加的某些位置的玩家超过了其容量,则添加为 util 的玩家,因为任何位置的玩家都可以添加到 util 中。