用01背包解决石子归并问题

来源:互联网 发布:wlk魔兽数据库 多玩 编辑:程序博客网 时间:2024/06/06 16:32

http://blog.csdn.net/w397090770/article/details/8028945

题目:有一堆石头质量分别为W1,W2,W3...WN.(W<=100000)现在需要你将石头合并为两堆,使两堆质量的差为最小。

     这道题目可以用01背包问题来解决。即求出和最接近sum/2的一个子集令f(i, j)表示前i个元素中和最接近j的子集的和(有点绕),则有: f(i, j) = max( f(i-1, j), f(i-1, j-a[i])+a[i] ) ,其中a数组是用来存储所有石头的质量的。

源码如下:

 

以下是参考代码:

#define N1 8int W1;int* Table[N1+1];int Weight[N1+1]={-1,3,41,25,6,2,3,7,10};int* Path[N1+1];void tet(){int sum=0;for(int i=1;i<N1+1;i++){sum+=Weight[i];}cout<<"sum:"<<sum<<endl;W1=sum>>1;for(int i=0;i<N1+1;i++){Table[i]=(int*)malloc(sizeof(int)*(W1+1));Path[i]=(int*)malloc(sizeof(int)*(W1+1));memset(Table[i],0,sizeof(int)*(W1+1));memset(Path[i],0,sizeof(int)*(W1+1));}for(int i=0;i<N1+1;i++){for(int j=0;j<W1+1;j++){Table[i][j]=-1;Path[i][j]=0;}}for(int i=0;i<N1+1;i++)Table[i][0]=0;for(int j=0;j<W1+1;j++)Table[0][j]=0;}int Calculate(){tet();for(int i=1;i<N1+1;++i){for(int j=1;j<W1+1;j++){Table[i][j]=Table[i-1][j];if(j>=Weight[i]){int t1=Table[i-1][j];int t2=Table[i-1][j-Weight[i]]+Weight[i];if(t2>t1)Path[i][j]=1;Table[i][j]=t2>t1?t2:t1;}}}int i=N1,j=W1;while(i>0&&j>0){if(Path[i][j]==1){j-=Weight[i];cout<<Weight[i]<<" ";}i--;}cout<<endl;return Table[N1][W1];}int main(){//tet();cout<<Calculate();return 0;}


 

也可以参考原文的代码:

#include <stdio.h>#define N 5// Author: 397090770// E-mail: wyphao.2007@163.com// 转载请注明。int do_(int *arr, int m){if(arr == NULL){return;}int i = 0, j = 0;int c[N + 1][100];//这个相当于上面的f(i,j)for(i = 0;i < N + 1; i++)//初始化    for(j = 0; j < 100; j++)    c[i][j]=0;    for(i = 1; i < N + 1; i++)    for(j = 1; j< m + 1; j++){        if(arr[i - 1] <= j){         if(arr[i - 1] + c[i-1][j-arr[i - 1]] > c[i-1][j])                c[i][j] = arr[i - 1] + c[i-1][j-arr[i - 1]];              else                 c[i][j] = c[i-1][j];        }else              c[i][j] = c[i-1][j];     }          //printf("%d\n", c[N][m]);return c[N][m];//最后一个就是最优值}int main(){int arr[N] = {/*1, 5, 7, 8, 9, 6, 3, 11, 20, 17*/5, 8, 13, 27, 14};int sum = 0;int i = 0;for(i = 0; i < N; i++){sum += arr[i];}int result = do_(arr, sum / 2);printf("%d\n", sum - 2 * result);return 0;}


 

原创粉丝点击