代码改变世界

动态规划模型2,01背包问题

2013-02-17 14:20  Dr.Ray  阅读(359)  评论(0)    收藏  举报

01背包问题:

      有n个物品,每个体积为v[1-n],问这些物品能否装满体积为b的背包,物品不能切分,形状因素忽略不计。求背包最小剩余空间。

 

阶段:以v数组的下标划分

状态:opt[]为0或1

状态转移方程:opt[j] = opt[j - v[i]]

 

思路:

      opt[b+1]代表体积为0~b的背包能否被装满,0否1能;

      于是就要知道所有物品体积组合之和。

      我理所因当想到用循环,多层循环强行组合不可能,因为循环层数不确定。

      可以用两层循环如//key!,先记一个物品v1体积的opt[v1]=1,接着只要体积v2于之前出现过的体积v1加上另一个物品的体积则opt[v2]=1。

      注意第二层必须用倒推,否则 j-v[i]会等于v[i],导致j = n*v[i]时也可以被填满,但是i物体只有一个,于是错误。

代码:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

 

int main()

{

     int v,n;

    FILE *fin;

    fin = fopen("in.txt","r");

    while(fscanf(fin, "%d%d", &v,&n) != EOF)

    {

         int opt[v+1], v[n];

         memset(opt, 0, sizeof(opt));

         opt[0] = 1;

         for(int i=0; i<n; i++)

         {

                fscanf(fin, "%d", v[i]);

          }

         

          //key!寻找每个可能的体积和

         for(int i=0; i<n; i++)

         for(int j = v; j>=v[i]; j--)

         {

                 if(opt[j - v[i]])

                 opt[j] = 1;

           }

 

         //找到最大的可行解

          for(int i=v; i>=0; i--)

          {

              if(opt[i] == 1)

              printf("%d\n", v-i);

           }

            return 0;

}