【武汉理工大学复试刷题】动态规划之分割等和子集、两人分配等额任务

题目描述

从 input 文件里读一个数组,大小为 6,分别代表任务量为1 2 3 4 5 6的任务 数,有两个助手,一个人可以完成多个任务。但是一个任务不能由两个人完成,任务量总数为偶数,请问有能让他们两个人分配任务量相同的方案吗, 例如
输入: 1 0 0 1 1 1
输出: no

思路分析

一开始以为这道题是任务分配问题,于是先去学匈牙利算法,但是和这道题对不上,看了群里才知道这其实是个01背包问题的变形,力扣也有原题。参考教程为 416.分割等和子集
总和的一半为背包容量,要找的是恰好能够放入背包的ij组合。
情况有三种:
①背包容量j==待取任务量tasks[i]
②j>tasks[i]
③j<tasks[i]
在这里插入图片描述

代码

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10

int max(int a,int b)
{
	return (a>b)?a:b;
}

int main()
{
	// 保存至新数组
	FILE *fp=fopen("./input.txt","r");
	int task = 6; // 任务类型
	int raw_tasks[6] = {1,2,3,4,5,6};
	int *tasks = (int*)malloc(sizeof(int)*MAXSIZE); // 迁移任务量+任务数量数组
	tasks[0]=0;
	int tmp=0; //形成新数组
	int count = 0; //总任务数量
	int sum=0; //总任务量(背包容量)
	for(int i=0;i<6;i++)
	{
		fscanf(fp,"%d",&tmp);
		//printf("tmp:%d\n",tmp);
		for(int j=0;j<tmp;j++)
		{	
	     	//将任务按任务数目顺序整合到一个数组中(tasks[0]置为0)
			if(tmp!=0)
			{
				tasks[count+1]=raw_tasks[i];
				count++;
				sum += raw_tasks[i];
			}
		}
	}

	for(int i=0;i<count;i++)
		printf("%d ",tasks[i]);
	printf("\n");
	if(sum%2==0)
	{
		// malloc二维数组dp,并初始化容量为0的状态
		int **dp=(int**)malloc(sizeof(int*)*(count+1));
		for(int i=0;i<=count;i++)
		{
			dp[i]=(int*)malloc(sizeof(int)*(sum/2+1));
			dp[i][0]=0;
		}
		for(int j=0;j<=sum/2;j++)
			dp[0][j]=0;
		// 核心代码
		for(int i=1;i<=count;i++)
		{
			for(int j=1;j<=sum/2;j++)
			{
				if(j==tasks[i]) // 恰好能放下
					dp[i][j] = 1;
				else if(j<tasks[i]) //放不下
					dp[i][j] = dp[i-1][j];
				else if(j>tasks[i]) //可以放下
						dp[i][j] = max(dp[i-1][j],dp[i-1][j-tasks[i]]);
				printf("%d ",dp[i][j]);
			}
			printf("\n");
		}
		if(dp[count][sum/2]==1)
			printf("yes\n");
		else
			printf("no\n");
	}
	else //不能被2整除则一定不可被均分给两人
	{
		printf("no\n");
	}
	getchar();
	
}

运行情况

结果

在这里插入图片描述

输入

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值