• 分支界限法 | 0-1背包问题(先入先出队列式分支限界法)


    输入要求

    有多组数据。

    每组数据包含2部分。
    第一部分包含两个整数C (1 <= C <= 10000)和 n (1 <= n <= 10,分别表示背包的容量和物品的个数。
    第二部分由n行数据,每行包括2个整数 wi(0< wi <= 100)和 vi(0 < vi <= 100),分别表示第i个物品的总量和价值

    输出要求

    对于每组输入数据,按出队次序输出每个结点的信息,包括所在层数,编号,背包中物品重量和价值。
    每个结点的信息占一行,如果是叶子结点且其所代表的背包中物品价值大于当前最优值(初始为0),则输出当前最优值 bestv 和最优解 bestx(另占一行)
    参见样例输出

    测试数据

    输入示例

    5 3
    2 2
    3 2
    2 3

    输出示例

    1 1 0 0
    2 2 2 2
    2 3 0 0
    3 4 5 4
    3 5 2 2
    3 6 3 2
    3 7 0 0
    4 9 5 4
    bestv=4, bestx=[ 1 1 0 ]
    4 10 4 5
    bestv=5, bestx=[ 1 0 1 ]
    4 11 2 2
    4 12 5 5
    4 13 3 2
    4 14 2 3
    4 15 0 0
     
     
    #include<stdio.h>
    #include<math.h>
    typedef struct {
        int no; // 结点标号 
        int id; // 节点id 
        int sw; // 背包中物品的重量 
        int sv; // 背包中物品的价值 
    }Node;
    
    void branchknap(int *w,int *v,int n,int c) {
    	int bestv = 0;
    	int f = 0;
    	int r = 0;
    	Node que[3000];
    	int path[15];
    	que[0].no = 1;
    	que[0].id = que[0].sv = que[0].sw = 0;
    	
    	while(f <= r) {
    		Node node = que[f];
    		printf("%d %d %d %d
    ",node.id+1,node.no,node.sw,node.sv);
    		
    		if(node.no >= pow(2,n)) {
    			if(node.sv > bestv) {
    				bestv = node.sv;
    				printf("bestv=%d, bestx=[",bestv);
    				int temp = node.no;
    				int i = 0;
    				while(temp > 1) {
    					if(temp % 2 == 0)
    						path[i] = 1;
    					else
    						path[i] = 0;
    					temp /= 2;
    					i++;
    				}
    				i--;
    				while(i >= 0) {
    					printf(" %d",path[i]);
    					i--;
    				}
    				printf(" ]
    ");
    			}
    		} else {
    			if((node.sw + w[node.id + 1]) <= c) {
    				r++;
    				que[r].id = node.id + 1;
    				que[r].no = node.no * 2;
    				int id = node.id + 1;
    				que[r].sv = node.sv + v[id];
    				que[r].sw = node.sw + w[id];
    			}
    			r++;
    			que[r].id = node.id + 1;
    			que[r].no = node.no * 2 + 1;
    			que[r].sv = node.sv;
    			que[r].sw = node.sw;
    		}
    		f++;
    	} 
    } 
    
    int main() {
    	int c,n;
    	int w[15],v[15];
    	while(~scanf("%d %d",&c,&n)) {
    		
    		for(int i = 1; i <= n; i++) {
    			scanf("%d %d",&w[i],&v[i]);
    		}
    		
    		branchknap(w,v,n,c);
    	}
    	
    	return 0;
    }
    

      

      

  • 相关阅读:
    C#获取当前程序运行路径的方法集合
    SQL为查询的结果加上序号(ROW_NUMBER) 合并多个查询结果
    Asp.net导出excel时长数字被科学计数法的解决方案。(身份证长数字作为字符处理)
    Stopwatch的用法
    对web.config的ConnectionString加密
    如何检索数据库中的空值和null
    如何将闲置的平板作为第二显示器(分屏)使用
    pyinstaller 打包文件太大
    如何让openssl生成的SSL证书被浏览器认可
    还是那该死的IE~~~
  • 原文地址:https://www.cnblogs.com/jj81/p/10146462.html
Copyright © 2020-2023  润新知