热身赛B.中国式家长(状压枚举)

本文介绍了一个关于技能养成的算法问题,玩家需要通过合理安排学习和活动来最小化悟性的消耗,最终完成所有技能的学习。涉及状态压缩、动态规划等算法思想。

鸡尾酒的寒假变得充实起来——因为又可以每天没日没夜地养孩子了.
游戏的每回合分为两个阶段,第一个阶段是学习阶段,可以花费一定的悟性学习技能.
有一条长度为的学习路径,只有当学习了路径上的第i个技能之后,才会在下一回合解锁第i+1个技能
(即每回合最多学习一个技能)
第个技能所需要花费的悟性为max(ki-A-B,ci).其中A,B为当前的智商值和情商值.
(初始状态为A=0,B=0.ki为第i个技能的最高花费,ci为第i个技能的最低花费)
第二阶段是安排活动阶段,可以选择一个已学的技能,并获得这个技能所能提供的智商值和情商值.
(如果当前什么技能都没有学,则跳过该阶段)
鸡尾酒想在Q回合后学完这条路径上所有N个技能,请你帮帮忙算一下悟性值的最小花费.

第一行输入两个正整数N,Q
接下来行描述学习路径上的N个技能,
每行包括4个数字,分别为ki,ci,ai,bi为该技能所能提供的智商值和情商值
其中:
1<=N<=Q<=15 0<=ai,bi<=1e9,0<=ki<ci<=1e9

输出一行一个整数代表在Q个回合后学完路径上的所有技能所需要的最小花费.

#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cstdio> 
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=1e5+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll k[20],c[20],a[20],b[20];//n个阶段最高花费最低花费 情商智商 
//状压枚举 回合数可以比掌握技能数多 
int main()
{
	ios::sync_with_stdio(false);
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		cin>>k[i]>>c[i]>>a[i]>>b[i];
	}
	
	ll minn=inf;//ci=1e9 n<=15 学n个 ll 
	//3e4状态 *20回合= 6e5 
	for(int i=0;i<(1<<q);i++)//000..00-15个1 q回合 2^q次方种状态 
	{//2^15=1024*32=3e4
		ll ab=0,maxab=0,ans=0,cnt=0; 
		for(int j=0;j<q;j++)//判断每一个回合是否学技能 比如15个回合 最大移14位 
		{
			if(i &(1<<j))//此回合学技能 判断此位是否为1 为1学 
			{
				ans+=max(k[cnt+1]-ab,c[cnt+1]);//当前累积的a+b 
				if(maxab<a[cnt+1]+b[cnt+1])
					maxab=a[cnt+1]+b[cnt+1];
				ab+=maxab;
				cnt++;//学了 到下次为1解锁下一阶段 
			}
			else
			{
				ab+=maxab;
			}
		}
		
		//求所有合法状态的最小花费 
		if(cnt!=n)//多了 少了 
		{
			continue;
		}
		else
			minn=min(ans,minn);//n<=q q回合一定能学会n个技能 
	} 
	cout<<minn<<endl;
	return 0;
} 
/*
3 5
10 0 3 3
20 5 1 2
50 10 100 100
*/ 
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define forn(i,n)  for(int i=0;i<n;i++)
#define rep(i,a,n) for(int i=a;i<=n;i++)
typedef long long ll;
const int maxn=5005;	//200堆 
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;

ll n,q;
ll a[25],b[25],k[25],c[25];
int main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i]>>k[i]>>c[i];
	}
	ll ab=0,maxab=0,ans=0,minn=inf,cnt=0;
	for(ll i=0;i<(1<<q);i++){
		ans=0,ab=0,maxab=0,cnt=0;//已掌握的最大情智商和 
		for(ll j=0;j<q;j++){
			if(i & (1<<j)){	//这一回合第一阶段学技能解锁 
				ans+=max(k[cnt+1]-ab,c[cnt+1]);//c不变 让ab尽量大 
				// 新学的是否最高 
				if(maxab<a[cnt+1]+b[cnt+1])	//已掌握技能中情智商最大值
					maxab=a[cnt+1]+b[cnt+1];
				ab+=maxab; 
				cnt++;	//掌握技能了 
			}
			else{	//不解锁下一个技能跳过该阶段 光练提高智情商 
				ab+=maxab;//+已学技能中提高最快的 减少悟性花费 
			}
		}
		if(cnt==n)
			minn=min(minn,ans);
		else
			continue; 
	}
	cout<<minn<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值