【动态规划】任务分配问题

题目来自贵大OJ


题目描述:给定n个零件需要的加工时间,分配到两台机床上加工,使得两台机床完成加工的时间尽可能同步。设计一个穷举搜索算法求解该问题。例如,有3个零件,加工时间分别为2、5和3,那么把加工时间为2、3的两个零件分配到一台机床上加工,把加工时间为5的零件分配到另一台机床上加工,两台机床能同时完工。

输入描述:每组数据的第一行是一个整数n (1 <= n <= 20)代表零件的数量。接下来有n行,每一行一个整数代表该零件所需的加工时间。

输出描述:对于每组测试数据,输出两台机床完工时间的最小差异。

样例输入

10
205 157 133 111 100 91 88 59 47 23

8
635 853 401 868 335 435 704 754

样例输出
0
3


【分析问题】对原问题稍加抽象,问题可以转化为:现有n个数,和为sum,分成两部分,使它们差的绝对值最小。即其中一部分元素的和<=sum/2,且是最接近sum/2的元素集合。

【解题思路】利用动态规划的解法。这其实类似于0-1背包问题,n个数相当于重量和价值相等的物品,要放入容量为sum/2的背包中。

使用一维数组dp存储,dp[j]表示前i个数和j最接近的累加值。

状态方程:dp[j]=max(dp[j],dp[j-num[i]]+num[i])

#include
#include
using namespace std;

int main()
{
    int num[21]; //0位置空出来
    int n,half,sum=0;
    cin>>n;
    for(int i=1;i<=n;i++){
       cin>>num[i];
        sum+=num[i];
    }
    half=sum/2;
    int dp[half+1]={0};

    for(int i=1;i<=n;i++)
        for(int j=half;j>=num[i];j--)
            dp[j]=max(dp[j],dp[j-num[i]]+num[i]);
            //dp[j]为num[i]不累加时的最大值
            //dp[j-num[i]]+num[i]为num[i]累加时的最大值
    
    int res=sum-2*dp[half];
    cout<

俗话说,大力出奇迹。下面顺便附上暴力法的代码。

【思路】下面利用了n位二进制数来表示数的所有状态。 规定二进制数位1代表在机器1,0代表在机器二。当二进制第一位为1时,累加进变量mach(表示机器1处理的零件),用sum减去两倍mach,即可得到差值。

#include
#include
using namespace std;

int main()
{
    int n,sum=0;
    int min=32767;//使min尽可能大,防止结果大于min
    int num[20]={0};
    cin>>n;
    for(int i=0;i>num[i];
        sum+=num[i];
    }
    
    for(int i=0;i=0;j--,t>>=1)
            mach+=(t%2)?num[j]:0;//当二进制最后一位为1,累加
        int tmp=abs(sum-2*mach);//求差值
        min=(min>tmp)?tmp:min;
    }

    cout<

你可能感兴趣的:(动态规划)