工作指派问题(运筹学)

题目是这样的:

    有4个工人,要分别指派他们完成4项工作,每人做各项工作的时间如下表:

                   A                B               C               D

    甲           15              18             21              24

    乙           19              23             22              18

    丙           26              17             16              19

    丁           19              21             23              17

    问指派哪人去做什么工作?

    问消耗时间最小是多少?

    

    传统的DP运筹问题,用 0—1规划 找好转移方程就行了。

 

#include <iostream>
#include <algorithm> 
#include <math.h>
#define maxn 0x3f3f3f3f
using namespace std;


/*........int p[4]={1,2,4,8}............................
..........配合int way[6][16] 的状态转移................. 
......................................................*/
int p[4]={1,2,4,8}; 

/*........int rec[6][16]................................
..........用于找出每个 way[a][state] 状态下的最小工时... 
......................................................*/
int rec[6][16];

/*........int way[6][16]................................ 
..........记录转移状态的数组,用于递归输出方案..........
..........用 0-1规划 构造 way[6][16]数组记录工人工作.... 
......................................................*/
int way[6][16];

/*........int map[4][4].................................
..........输入数据 .....................................
..........用于存储每个工人的每项工作耗时................ 
......................................................*/
int map[4][4]={{15,18,21,24},{19,23,22,18},{26,17,16,19},{19,21,23,17}};


/*........int f(int a,int state)........................
..........前a个人,当前状态为state的时候的最小耗费时间..
..........state是一个2进制的数,大小是从0000-1111.......
..........当state从低到高,第i位的数为0,就表示之前第i项工作没有安排人做,为1表示做了
......................................................*/
int f(int a,int state)
{
    if (a==5 && state==15) return 0;
    if (rec[a][state]!=maxn) return rec[a][state]; 
    for (int i=0;i<4;i++)
        if ( ((p[i]&state)!=p[i]) && (f(a+1,state|p[i])+map[a-1][i])<rec[a][state] )
		{
           rec[a][state]=f(a+1,state|p[i])+map[a-1][i];
           way[a][state]=state|p[i];
        }
    return rec[a][state];
}

/*........void out(int a,int state).....................
..........前a个人,当前状态为state的时候的最小耗费时间..
..........int func(int a)............................... 
..........通过第a个人的 way[a][state]状态数组^state 找出第a个人的工作 
......................................................*/
int func(int a)
{
    for (int i=0;i<4;i++)
	    if (a==p[i]) return i+1; 		       
}
void out(int a,int state)
{
    if (a==5) return; 
    printf("第%d个人做第%d项工作\n",a,func(way[a][state]^state));
    out(a+1,way[a][state]);
}

int main(void)
{
    int i,j;
    for (i=0;i<6;i++)
        for (j=0;j<16;j++)
            rec[i][j]=maxn;
    printf("最小消耗时间:%d\n",f(1,0));
    printf("方案如下:\n");
    out(1,0);
    return 0;    
}
/*最小消耗时间:70......................................
方案如下:..............................................
第1个人做第1项工作......................................
第2个人做第4项工作......................................
第3个人做第3项工作......................................
第4个人做第2项工作....................................*/

  Copy的@ jacksonislwj 的代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值