对于一些枚举,枚举子集,分组等问题,同样可以利用搜索回溯来解,这种题基本类型为取与不取或者放或不放的形式,需要分两条路来讨论。
解题思路:
(1)对于本题,可以理解为分割问题,分割每一门课的题目,如何分割呢?题中说一个大脑可以同时的独立运行,要求所耗费的时间最少,意思是一道题解完立马补充下一道题,而且两边越平均越好,这样大脑就不会有空闲的时间,达到效率最高
(2)每科都是独立的,解完一科才能写下一科,那么搜索4次即可
(3) 我们现在把大脑分成左边和右边,依次枚举将每道题放入左边或者不放,什么时候放呢?当然是左脑做题的时间小于等于总共时长的一半的时候放,因为要尽量让左右脑平衡。然后再考虑不放入左脑的情况
(4)设DFS函数(int x,int cnt,int Time)分别表示做第x门课,到第cnt道题的总共时长为Time
下一门课的时候Time清零,dfs(i,1,0),开始枚举第一道题,如果Time+aa[cnt]<=sum/2的,说明将这道题可以加入左脑,那么Time增加,开始枚举下一题,等到递归函数执行完,再恢复现场
(5)同时也要枚举这一道题不加入左脑的情况,继续dfs(i,cnt+1,TIme)的递归
(6)递归的出口是什么呢?枚举完这门课的所有题后,取消耗时间尽可能大的,因为越接近总时长的一半越好,然后本门课的最优时间就是Time-sum
#include<bits/stdc++.h>
using namespace std;
int a[5],aa[30];
int res,ans,sum;
//x为统计第几科目,cnt为本科的题目数量,Time为所消耗的时间
void dfs(int x,int cnt,int Time)
{
if(cnt>a[x])//当枚举完本科的所有题目
{
res=max(res,Time);//取较大值
return ;//结束递归
}
if(Time+aa[cnt]<=sum/2)//如果加入这道题时长没有超过sum/2
{
Time+=aa[cnt];//保存现场
dfs(x,cnt+1,Time);//加入,进入下一层的递归
Time-=aa[cnt];//恢复现场
}
dfs(x,cnt+1,Time);//这道题时长不加入的话,枚举下一道题
}
int main()
{
cin>>a[1]>>a[2]>>a[3]>>a[4];
for(int i=1;i<=4;i++)
{
sum=0;//统计本科的总时长
for(int j=1;j<=a[i];j++)
{
cin>>aa[j];
sum=sum+aa[j];//统计本科的总时长
}
res=0;//统计本科的最优时长
dfs(i,1,0);//开始深搜
ans=ans+(sum-res);//累加最优解
}
cout<<ans;
return 0;
}