算法-任务分配-DP

题意

有M个任务,分给K个队完成。

任务分配需要连续,比如:

合法-------1队:0-5;2队:6-10
不合法----1队:0-5;2队:6-9;1队:10

每个任务有难度值D[i];每个队做完任务后,根据难度产生疲劳度T,疲劳度计算方式:

1、完成单个任务,T=0;
2、完成多个任务:
任务4到5,T=D[4]*D[5]
任务2到4,T=D[2] *(D[3]+D[4])+D[3] * D[4]
任务i到j:
T=
D[ i ] * (D[i+1] + D[i+2]…+D[j])+
D[i+1] * (D[i+2] …+ D[j])+

D[j-1] * D[j]

分配任务,求所有队伍疲劳度之和,最小值。

0<M<10000
0<K<200
0<D[i]<100

示例

输入:
2 1 -----2个任务,1个队伍
5 7 -----难度:任务0:5,任务1:7
输出:
35

输入:
4 2
1 2 6 1
输出:
8

#include<stdio.h>
#define MIN(a,b) (a)<(b)?(a):(b)
#define MAX(a,b) (a)>(b)?(a):(b)
unsigned int D[10000];//每个任务的难度
int M, K;//M个任务K个队伍
unsigned int D_sum_i_j[10000][10000];//i--j的任务,简简单单求和
unsigned int T_ij[10000][10000];//i--j的任务分配给一个队伍所产生的tired
unsigned int dp[10000][200];//下标0--i任务分给前j个队伍做,最小的tired总和
void input();
unsigned int add_overflow(unsigned int x, unsigned int y);
unsigned int mul_overflow(unsigned int a, unsigned int b);
/*
 4 2
 1 2 6 1
 
 5 2
 2 1 8 1 8
 
 2 1
 5 7
*/
int main()
{
	int i, j, k;
	input();
	for (i = 0; i < M; i++)//遍历出所有i到j的D的和----D_sum_i_j,给T_ij用
	{
		D_sum_i_j[i][i] = D[i];
		for (j = i+1; j < M; j++)
		{
			D_sum_i_j[i][j] = D_sum_i_j[i][j-1] + D[j];
		}
	}
	for (i = 0; i < M; i++) //遍历出所有i到j的T,给dp用
	{
		T_ij[i][i] = 0;
		for (j = i + 1; j < M; j++)
		{
			//T_ij[i][j] = T_ij[i][j - 1] + D_sum_i_j[i][j-1]* D[j];
			T_ij[i][j] =
				add_overflow(T_ij[i][j - 1],
							 mul_overflow(D_sum_i_j[i][j - 1], D[j])
				             );
		}
	}
	for (j = 1; j <= K; j++)
	{
		for (i = j-1; i < M; i++)
		{
			if (i == j - 1)
				dp[i][j] = 0;
			else if (j==1)
			{
				dp[i][j] = T_ij[0][i];
			}
			else
			{
				dp[i][j] = UINT_MAX;
				for (k = j - 2; k < i - 1; k++)
				{
					//0-i的任务,分给j个队伍,产生的最小T,由下面递推:
					//0-k的任务,分给前j-1个队伍,最后一个队伍再分k+1到i。
					//遍历所有可能的k,取最小的
					//dp[i][j] = MIN(dp[i][j], dp[k][j - 1]+ T_ij[k+1][i]);
					dp[i][j] = 
						MIN(dp[i][j], 
							add_overflow(dp[k][j - 1], T_ij[k + 1][i])
						    );
				}
			}
		}
	}

}

void input()
{
	int i = 0;
	scanf("%d %d", &M, &K);
	for (i = 0; i < M; i++)
	{
		scanf("%d", &D[i]);
	}
}

unsigned int add_overflow(unsigned int x, unsigned int y)
{
	if (y > UINT_MAX - x)
		return UINT_MAX;
	return x + y;
}
unsigned int mul_overflow(unsigned int a, unsigned int b)
{
	if (UINT_MAX / a < b) {
		return UINT_MAX;
	}
	return a * b;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值