#include <stdio.h>
#include <math.h>
#include <stdlib.h>
// global parameteres
int MAX_NUM_OF_ITERS = 100;
int MAX_TIME = 30; //max 30 sec comp time.
int NB_METHOD=1; //0: first descent 1: best descent
/*The following is problem data. For convenience, we
include in the program. For real applications, the data
should be loaded from file(s).*/
int NUM_OF_ITEMS=100; //
int CAPACITY=1000;
int p[] = {11, 11, 10, 12, 3, 5, 13, 6, 10, 12, 19, 8, 3, 19, 3, 7, 8, 17, 8, 3, 5, 3, 5, 5, 13, 9, 9, 4, 11, 20, 18, 5, 17, 19, 14, 4, 14, 7, 17, 6, 9, 7, 12, 20, 3, 9, 12, 4, 7, 13, 20, 3, 18, 4, 12, 10, 3, 20, 4, 4, 13, 17, 16, 4, 5, 16, 18, 8, 18, 20, 9, 10, 10, 16, 18, 20, 3, 5, 17, 16, 13, 11, 3, 10, 20, 12, 6, 6, 11, 18, 18, 14, 19, 6, 18, 9, 14, 12, 10, 19};
int v[] = {93, 108, 82, 67, 82, 88, 77, 60, 138, 135, 93, 92, 128, 134, 144, 75, 148, 133, 150, 103, 79, 82, 106, 143, 99, 101, 80, 90, 84, 62, 90, 95, 119, 75, 101, 93, 85, 118, 81, 64, 87, 113, 117, 142, 88, 134, 134, 100, 112, 103, 90, 149, 122, 145, 92, 63, 103, 140, 62, 138, 60, 103, 145, 143, 109, 117, 63, 65, 124, 78, 121, 114, 96, 99, 110, 125, 95, 92, 70, 70, 149, 115, 148, 85, 81, 62, 99, 124, 91, 101, 118, 130, 140, 86, 97, 138, 89, 63, 122, 112 };
// 每个对象的具体元素
struct item{
int indx; // 排序后记住索引
int p;
int v;
double ratio;
};
struct problem{
int C; // int CAPACITY=1000;
int num_of_items; // int MAX_NUM_OF_ITERS = 100;
struct item* items;
};
struct solution{
int objective;
int cap_left;
struct problem* prob;
int* x;
};
// 对问题初始化,赋变量
struct problem* init_prob(){
struct item* my_item = malloc(sizeof(struct item)*NUM_OF_ITEMS);
for(int i=0; i<NUM_OF_ITEMS; i++){
my_item[i].indx=i;
my_item[i].p=p[i];
my_item[i].v=v[i];
}
struct problem* my_prob = malloc(sizeof(struct problem));
my_prob->C =CAPACITY;
my_prob->num_of_items = NUM_OF_ITEMS;
my_prob->items = my_item;
return my_prob;
}
// 用来清空内存
void free_problem(struct problem* my_prob) {
if(my_prob!=NULL){
free(my_prob->items); //free item array
free(my_prob);
}
}
//create an empty solution
struct solution* create_empty_sol(struct problem* my_prob) {
struct solution* my_sln = malloc(sizeof(struct solution));
my_sln->prob = my_prob;
my_sln->objective=0; my_sln->cap_left=my_prob->C;
my_sln->x = malloc(sizeof(int)*my_prob->num_of_items);
for(int i=0; i<my_prob->num_of_items; i++) my_sln->x[i]=0;
return my_sln;
}
struct solution* copy_from(struct solution* sln){
struct solution* my_sln = malloc(sizeof(struct solution));
my_sln->prob = sln->prob; //shalow copy
my_sln->objective=sln->objective; my_sln->cap_left=sln->cap_left;
my_sln->x = malloc(sizeof(int)*sln->prob->num_of_items);
for(int i=0;i<sln->prob->num_of_items; i++)
my_sln->x[i] = sln->x[i];
return my_sln;
}
// 用来清空内存
void free_solution(struct solution* sln){
if(sln!=NULL){
free(sln->x);
free(sln);
}
}
void print_sol(struct solution* sln, char* sol_name){
printf("%s's objective = %d, cap left = %d\n",sol_name, sln->objective, sln->cap_left);
//checking anormaly in the solution struct.
int cap=0, obj=0;
for(int i=0; i<sln->prob->num_of_items; i++){
if(sln->x[sln->prob->items[i].indx]>0){
obj += sln->prob->items[i].p;
cap +=sln->prob->items[i].v;
}
}
if(obj != sln->objective) {
printf("Inconsistent objective value. Correct val = %d\n", obj);
}
if(sln->prob->C - cap != sln->cap_left){
printf("Inconsistent residual capacity value. Correct val =%d\n",
sln->prob->C- cap);
}
}
int cmpfunc (const void * a, const void * b) {
const struct item* item1 = a;
const struct item* item2 = b;
if(item1->ratio>item2->ratio) return -1;
if(item1->ratio<item2->ratio) return 1;
return 0;
}
int cmpfunc2 (const void * a, const void * b) {
const struct item* item1 = a;
const struct item* item2 = b;
if(item1->indx>item2->indx) return 1;
if(item1->indx<item2->indx) return -1;
return 0;
}
// !!!!!!!!!! ↓
//greedy heuristic by packing highest pi/vi
struct solution* greedy_heuristic(struct problem* prob){
if(prob==NULL){ // 检查问题是否存在
printf("Missing problem data, please check!\n");
exit(1);
}
struct solution* greedy_sln =create_empty_sol(prob); // 建立 solution
int n = prob->num_of_items;
for(int i=0;i<n; i++){
prob->items[i].ratio = (double)prob->items[i].p/prob->items[i].v;
//printf("ratio[%d]=%.3f\t",prob->items[i].indx,prob->items[i].ratio);
}
//sort items according to ratio
qsort(prob->items, n, sizeof(struct item), cmpfunc);
greedy_sln->cap_left=prob->C; greedy_sln->objective=0;
for(int i=0;i<n; i++){
//printf("ratio[%d]=%.3f\t",prob->items[i].indx,prob->items[i].ratio);
if(greedy_sln->cap_left>= prob->items[i].v){
greedy_sln->x[prob->items[i].indx]=1;
greedy_sln->cap_left -= prob->items[i].v;
greedy_sln->objective += prob->items[i].p;
}
}
//make sure original order to items is restored to match index in x
qsort(prob->items, n, sizeof(struct item), cmpfunc2);
//print_sol(greedy_sln, "Greedy Solution");
return greedy_sln;
}
// Fist fit
struct solution* first_descent(struct solution* curt_sln) { //使用配对交换
int item1, item2;
struct solution* new_sln = copy_from(curt_sln); // 引入 original solution
for(int i=0; i<NUM_OF_ITEMS; i++) {
if(curt_sln->x[i]>0){ // 如果当前的 x_i 解 在背包里
item1 =i;
for(int j=0; j<NUM_OF_ITEMS; j++){ // 搜索是否有其他更适合的值
int v1 = curt_sln->prob->items[item1].v; // 遍历时当前的一个 item 的 volumn
int v2 = curt_sln->prob->items[j].v; // 每一个 item 的 volumn
if(i!=j && curt_sln->x[j]==0 && curt_sln->cap_left + v1 >= v2) { // x_i 加进来后还有剩余 capacity
item2=j;
int delta =curt_sln->prob->items[item2].p -
curt_sln->prob->items[item1].p;
if(delta >0){
new_sln->x[item1]= 0;
new_sln->x[item2]= 1; //换 P 更大的进来
new_sln->objective=curt_sln->objective + delta; //delta evaluation
new_sln->cap_left = new_sln->cap_left - v2 + v1;
//print_sol(new_sln, "First Descent Solution");
return new_sln;
}
}//endif
}//endfor
}//endif
}//endfor
return NULL;
}
// best fit
struct solution* best_descent(struct solution* curt_sln) {
int item1, item2;
int best_delta = -1000, b_item1=-1, b_item2=-1; //store the best move
struct solution* new_sln = copy_from(curt_sln);
for(int i=0; i<NUM_OF_ITEMS; i++)
{
if(curt_sln->x[i]>0){ // 同上
item1 =i;
for(int j=0; j<NUM_OF_ITEMS; j++){
int v1 = curt_sln->prob->items[item1].v;
int v2 = curt_sln->prob->items[j].v;
if(i!=j && curt_sln->x[j]==0 && curt_sln->cap_left + v1 >= v2) {
item2=j;
int delta =curt_sln->prob->items[item2].p -
curt_sln->prob->items[item1].p;
if(delta >0 && delta>best_delta){
b_item1 = item1;
b_item2 = item2;
best_delta= delta; // x_i 和 x_j 的差值
}
}
}//endfor
}//endif
}//endfor
if(best_delta>0){
new_sln->x[b_item1]= 0;
new_sln->x[b_item2]= 1; //swap
new_sln->objective=curt_sln->objective + best_delta;
//delta:x_i 和 x_j 交换后 p 的差值;objective:目标函数值
int v1 = curt_sln->prob->items[b_item1].v;
int v2 = curt_sln->prob->items[b_item2].v;
new_sln->cap_left = new_sln->cap_left - v2 + v1;
//print_sol(new_sln, "Best Descent Solution");
return new_sln;
}
else
return NULL;
}
struct solution* local_search(struct solution* init_sln, int nb_method){
struct solution *nb_sln, *curt_sln;
curt_sln = copy_from(init_sln);
for(int k=0; k< MAX_NUM_OF_ITERS; k++)
{
if(NB_METHOD==0)
nb_sln=first_descent(curt_sln); //first descent local search
else nb_sln=best_descent(curt_sln); //best descent local sarch
if(nb_sln!=NULL)
{
free_solution(curt_sln);
curt_sln= copy_from(nb_sln);
free_solution(nb_sln);
}
}
return curt_sln;
}
int main()
{
//problem* prob = loaddata("knapsack.txt");
struct problem* prob = init_prob();
// original solution
struct solution* init_sln = greedy_heuristic(prob); // 贪婪算法
print_sol(init_sln,"Initial Solution");
// local optimasation solution
struct solution *local_optimum_sln;
local_optimum_sln = local_search(init_sln, NB_METHOD); //local search
print_sol(local_optimum_sln, "Local Optima Solution");
//free memory for all pointers
free_problem(prob);
free_solution(init_sln);
free_solution(local_optimum_sln);
return 0;
}
lp_solve 解决 1D 背包问题
最新推荐文章于 2024-09-04 14:45:59 发布
本文提供了一个使用C语言实现的程序,该程序采用贪婪算法初始化解,然后通过第一下降法或最佳下降法进行局部搜索优化,以解决0-1背包问题。程序首先计算物品价值/重量比例并排序,接着执行局部搜索策略寻找更优解,并最终输出优化后的解决方案。
摘要由CSDN通过智能技术生成