【分割问题】-临时抱佛脚

kkksc03考前临时抱佛脚 - 洛谷


对于一些枚举,枚举子集,分组等问题,同样可以利用搜索回溯来解,这种题基本类型为取与不取或者放或不放的形式,需要分两条路来讨论。

解题思路:

(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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值