题目描述
从 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();
}