题解 CF1042B 【Vitamins】

小蒟蒻第一道蓝题(虽然很水),发篇题解纪念一下。

题解里已经有很多深搜 dfs 了,但没有一篇广搜 bfs 的题解,没有和我重复的解法,那我就发一篇 bfs 的题解吧。

PS:第一次看到这题是在一次校内模拟赛。那时候我很菜,就全部直接输出 “(-1)”,想骗点分。没想到毒瘤 lbn 一个无解的数据都没给,当场爆零 (ldotsldots)

咳咳,接下来是正题。 首先,要再次引用机房奆佬的一句话。

那就,死磕出一个搜索吧。

我的大体思想是:用一个结构体类型的队列来分别记录搜索到各个状态下的维生素含量情况和总价值。当每种维生素都有的时候,就更新答案;否则就继续往下一层拓展(ldotsldots) 直到全部搜完,此时的答案就是最优了。(具体操作我会在代码注释中说。)

本题的思维难度不高,但细节还是要注意的。

另外这题要想靠搜索过,无论 dfs 还是 bfs,都需要剪枝,不然就会像我前几次提交一样 T 飞。(剪枝部分详见代码注释。)

完整 AC 代码:

#include<bits/stdc++.h>
using namespace std;
struct node    //结构体,v 数组表示目前维生素情况,idx 表示目前搜到的编号,p 表示目前的总价值。 
{
	bool v[3];
	int idx;
	long long p;    //三年 OI 一场空,不开 long long 见祖宗。 
}a[1005];
int n;
long long ans=9223372036854775807; 
bool book[3];       //这是用来判断是否无解的。 
string s;
queue<node> q;                //STL大法好 。 
void bfs()
{
	while(q.empty()==0)    
	{
		node now=q.front();
		q.pop();
		if(now.v[0]&&now.v[1]&&now.v[2])   //如果满足条件,就更新答案。 
			if(now.p<ans)
				ans=now.p;
		for(int i=now.idx+1;i<n;i++)    //否则,继续往下拓展。 
		{                      //从目前的编号往后搜,可以不重复。
			node hsy;
			hsy.p=now.p+a[i].p;
			hsy.idx=i;
			if(hsy.p>ans)         //注意!!!这里的剪枝很重要。			                       
				continue;         //如果往下拓展的总价值超过了目前的答案,就没有继续拓展的必要了。
			if(now.v[0]||a[i].v[0])   //处理维生素的情况。 
				hsy.v[0]=1;
			else
				hsy.v[0]=0;
			if(now.v[1]||a[i].v[1])
				hsy.v[1]=1;
			else
				hsy.v[1]=0;
			if(now.v[2]||a[i].v[2])
				hsy.v[2]=1;
			else
				hsy.v[2]=0;
			q.push(hsy);       //入队,继续拓展。 
		}
	}
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a[i].p>>s;
		a[i].idx=i;
		for(int j=0;j<s.length();j++)
			a[i].v[s[j]-'A']=1,book[s[j]-'A']=1;    //处理单独每种果汁的维生素。 
	}
	if(book[0]==0||book[1]==0||book[2]==0)   //这里也是剪枝,看是否无解 。 
	{
		cout<<-1;
		return 0;
	}
	for(int i=0;i<n;i++)    //分别从各种果汁开始搜索。 
	{
		q.push(a[i]);
		bfs();
	}
	cout<<ans;     //此时答案就是最优了。 
	return 0;
} 

小蒟蒻写个题解也不容易,逃。

原文地址:https://www.cnblogs.com/win10crz/p/12859650.html