C: 试题 I糖果 第十届蓝桥杯C/C++ A组(纯dp状压)

【问题描述】
糖果店的老板一共有 M 种口味的糖果出售。为了方便描述,我们将 M 种口味编号 1 ~ M。
小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而 是 K 颗一包整包出售。
幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。
给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。

【输入格式】
第一行包含三个整数 N、M 和 K。
接下来 N 行每行 K 这整数 T1, T2, · · · , TK,代表一包糖果的口味。
【输出格式】
一个整数表示答案。如果小明无法品尝所有口味,输出 -1。
【样例输入】
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2

【样例输出】
2
对于所有评测样例,1 ≤ N ≤ 100,1 ≤ M ≤ 20,1 ≤ K ≤ 20,1 ≤ Ti ≤ M 。

纯dp状压

#include<stdio.h>
#include<math.h>
	int N,M,K;
	int i,j;
	int f; 
	long int NB[100]={0};//因为M<=20 
	long int status[101]={0};
	int OVER=0;

		void dp(int d,int f)
	{   
		if(OVER==0)
		{
		if(status[d-1]!=(pow(2,M)-1)) 
		{
			if(f>0)
		if((N+1-d)>=f)
		{
			status[d]=NB[d]|status[d-1];
			dp((d+1),(f-1));
			status[d]=status[d-1];
			dp((d+1),f);
		}
	//不return,数据已存在全局变量里 
		}	
		else {
			OVER=1;
		}	
	}
	}
		int dsp(int i,int j)
	{
		int a;
		dp(i,j);
		a=OVER;
		for(i=0;i<=N;i++)status[i]=0;
		OVER=0;
		return a;
	}
int main()
{
	scanf("%d %d %d",&N,&M,&K);
	for(i=1;i<=N;i++)
	{
		for(j=0;j<K;j++) 
		{
		scanf("%d",&f);
		NB[i]=NB[i]|(long int)(pow(2,(f-1)));
		}
	}

	for(i=1;i<=N;i++)
	{
		if(dsp(1,i)) 
		      {
		     	printf("%d\n",i);
			   break;
	           	}
	}
if(i==(N+1))printf("-1");
	return 0;
 } 
### 第十届蓝桥杯 C++ A 题目及解答 #### 一、题目概述 第十届蓝桥杯大赛中的C++ A涉及多个算法和编程技巧的应用。其中,部分典型题目包括但不限于字符串编码问题以及基于深度优先搜索(DFS)的合优化问题。 对于字符串编码问题,可以通过三层嵌套循环来实现对特定数值范围内的字符映射计算[^1]。而对于更复杂的合优化问题,则可借助DFS技术完成解决方案的设计与实施[^2]。 以下是具体实例解析: --- #### 二、字符串编码问题分析 给定整数`N=2019`,将其转换成由字母成的三字符形式表示法。假设每一位上的取值是从1至26之间的一个正整数,分别对应英文字母表中的'A'到'Z'。那么整个过程实际上就是寻找满足条件的一(i,j,k),使得表达式 `i*26*26+j*26+k==2019` 成立。 下面是解决该问题的核心代码片段: ```cpp #include <iostream> using namespace std; int main(){ bool found = false; for(int i=1;i<=26 && !found;i++) for(int j=1;j<=26 && !found;j++) for(int k=1;k<=26 && !found;k++){ if((long)(i)*26*26+(j)*26+(k)==2019){ char c_i='A'+(i)-1,c_j='A'+(j)-1,c_k='A'+(k)-1; cout<<c_i<<""<<c_j<<""<<c_k<<"\n"; found=true; } } } ``` 上述程序通过穷举所有可能性找到符合条件的结果并打印出来。 --- #### 三、糖果分配问题详解 此题要求我们考虑如何利用最少数量的不同类型的糖果包覆盖全部所需口味种类。考虑到某些特殊情况下同一种类可能会重复出现多次的情况,因此引入了一个计数器数代替传统的布尔标志位来进行态跟踪。 下面展示的是一个简化版的递归函数框架用于探索最优路径的选择策略: ```cpp void dfs(int current_taste, int total_bags) { // 如果已经收集齐所有的味道则更新最小值 if(allTastesCollected()) { ans = min(ans, total_bags); return ; } // 超过最大允许尝试次数提前结束 if(total_bags >= bestKnownAnswerSoFar)return ; // 尝试加入新的袋子或者继续当前序列 for(auto option : availableOptions){ addOption(option); // 添加选项 dfs(current_taste + getFlavorsInBag(option),total_bags+1); removeLastAdded(); // 回溯移除最后添加项 } } ``` 以上伪码展示了基本逻辑结构,实际应用时还需要补充细节比如初始化参数设置等操作。 --- ### 结论 综上所述,在面对诸如第十届蓝桥杯这样的竞赛挑战时,掌握基础数据结构与经典算法至关重要。无论是简单的数学建模还是复杂的态空间搜索都需要扎实的基础知识作为支撑才能高效解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值