01背包问题

 
(DP)01背包问题
/*
* =====================================================================================
*
*       Filename:  Bag01.c
*
*    Description:  01背包问题
*                                      有N个物品, 重量分别为w1到wn,价值分别为v1到vn,有一个承重为C的包,问该将哪些物品放入包
*                                      中可使得包中物品的价值和最大, 设m[i][j]代表在承重为j,可供装包的物品编号为从i(包括i)
*                                      到N时的最大价值(物品的最小编号为1),则此时递推公式为
*                                      m[i][j] = max(m[i+1][j], m[i+1][j-wi] + vi) //两种情况:取物品i和不取物品i,从这两种情况中取最大值
*        Version:  1.0
*        Created:  2010年08月25日 08时59分40秒
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  glq2000 (), [email protected]
*        Company:  HUE ISRC
*
* =====================================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX(A,B) (((A)>(B))?(A):(B))
#define N 7      //物品个数
#define C 19     //包的承重
int   w [N + 1 ]   =   { 0 ,   3 ,   7 ,   2 ,   4 ,   8 ,   10 ,   5 };   //w[i]:物品i的重量, 简单起见,w[0]不使用
int   v [N + 1 ]   =   { 0 ,   2 ,   10 ,   3 ,   5 ,   7 ,   12 ,   6 }; //v[i]:物品i的价值, 简单起见,v[0]不使用
int   m [N + 1 ][ C + 1 ]; //加1的目的是为了使用方便,m[i][j]表示在承重为j,可供装包的物品编号为从i(包括i)到N时的最大价值(物品的最小编号为1)

void   MaxBagValue( int  ( * m )[ C + 1 ],   int  n ,   int   c ,   int   * w ,   int   * v);    //计算m[i][j]数组
void   Output( int  ( * m )[ C + 1 ]);               //输出m[i][j]数组
void   TraceBack( int  ( * m )[ C + 1 ]);            //求出被选择的物品的编号

int   main()
{
          MaxBagValue( m ,  N ,   C ,   w ,   v);
          Output( m);   printf( " \n\n\n\n ");
          printf( "MaxBagValue: %d \n\n " ,   m [ 1 ][ C ]);
          TraceBack( m);

          return   0;
}


/*
*m[i][j]表示在承重为j,可供装包的物品编号为从i(包括i)到N时的最大价值(物品的最小编号为1)
*w[i] 重量, v[i] 价值, c当前包中剩余承重, n 当前可供装包的编号为从n(包括n)到N
*/
void   MaxBagValue( int  ( * m )[ C + 1 ],   int  n ,   int   c ,   int   * w ,   int   * v)
{
          int   i ,   j;
          for( j = 1;   j <= c;   ++ j)
                  if( j   >=   w [N ])
                          m [N ][ j ]   =   v [N ];

          for( i =n - 1;   i >= 1;   -- i)
          {
                  for( j = 1;   j <= c;   ++ j)
                  if( j   >=   w [ i ])
                          m [ i ][ j ]   =   MAX( m [ i + 1 ][ j ],   m [ i + 1 ][ j - w [ i ]] + v [ i ]);
                  else
                          m [ i ][ j ]   =   m [ i + 1 ][ j ];
          }
}


void   Output( int  ( * m )[ C + 1 ])                //输出m[i][j]数组
{
          int   i , j;
          for( i = 1;   i <=N;   ++ i)
          {
                  printf( "w[%d]=%d  " ,   i ,   w [ i ]);
          }
          printf( " \n ");
          for( i = 1;   i <=N;   ++ i)
          {
                  printf( "v[%d]=%d  " ,   i ,   v [ i ]);
          }
          printf( " \n\n ");

          for( i = 0;   i <=N;   ++ i)
          {
                  for( j = 0;   j <= C;   ++ j)
                  {
                          printf( "m[%d][%d]=%d " ,   i ,   j ,   m [ i ][ j ]);
                  }
                  printf( " \n\n ");
          }
}


//利用m数组求出哪些编号的物品被选中了
void   TraceBack( int  ( * m )[ C + 1 ])
{
          printf( "Seletced: ");
          int   i = 1 , j = C;
          while( j   &&   i <=N)
          {
                  if( i ==N   &&   j > 0   &&   m [ i ][ j ] == v [ i ])
                  {
                          printf( "%d " ,   i);
                          j   -=   w [ i ];
                          ++ i;
                  }
                  if( m [ i ][ j ]   >   m [ i + 1 ][ j ])
                  {
                          printf( "%d " ,   i);
                          j   -=   w [ i ];
                          ++ i;
                  }
                  else
                          ++ i;
          }
          printf( " \n ");
}

你可能感兴趣的:(c,gcc,compiler,output,2010)