SDU程序设计与实践模拟Week6

本文详细解析了SDU程序设计与实践模拟Week6A的掌握魔法の东东II题目,采用C++代码实现,通过枚举和判断策略解决组合数学问题。介绍了炸弹、同花、顺子等扑克牌组合的判断逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SDU程序设计与实践模拟Week6

A- 掌握魔法の东东 II

题目
Input&&Output:
INPUT&&OUTPUT
sample:

#Input
5 2
1 0 3 1
#Output
0 0 0 0 8 0 12 36 0
#Input
25 4
0 0 24 3
#Output
0 2 18 0 0 644 1656 36432 113344

题解

1.本题粗略以看是一道组合数学的问题,然鹅这么做不是不可以但是太烦了(本人尝
试了最终头秃放弃 哭.jpg)
2.我们细心观察可以发现本题实际上直接枚举就可以做,毕竟只有上限100个数,从
中取三个不重复的数,三重循环也不会超时。
3.取出数以后就是判断阶段,先说一下我的思路(low爆了):
首先我发现很多判断的结果都是由关联的,因此先排序
然后炸弹我们发现是按照数字大小排序后 前四个或后四个数相同 实际上就是0~3或1~4(两对或一对或三条也可以这么判断)
同花其实是花色排序
顺子实际上就是判断后一项是否比前一项大一
剩余的就是杂牌

PS:后读过某大佬的代码,发现自己写的代码low爆了,做一个简述,实际上不需要
建立struct直接写映射就好,其次我循环处的取数也写的很冗余,实际上内层直接取
就可以了,外部的暂时保存属实所欲,最后就是关于结果的判断,其实大佬的判断的
思想也差不多,但是他的代码很简洁,比如我们可以直接存储数组中相同数的个数然
后从个数先进行判断,顺子的判断实际上差不多但是可以不建中间数组直接循环使用
bool值判断。

C++代码

#include<iostream>
#include<algorithm>
using namespace std;
struct c{
	int num,col;
	
	bool operator<(c &x){
		if(num!=x.num) return num<x.num;
		return col<x.col;
	}
	
	bool operator==(c &x){
		return num == x.num;
	}
};
int A,B,x,y;
int pos=0;
c curr;
c poke[5];
c poke2[5];
int ans[9];
void init(){
	for(int i = 0;i<9;i++) ans[i] = 0;
}
void get(int i){
	x = i/B;
	y = i%B;
	curr.num = x;
	curr.col = y;
}
int aa = 0;
bool same(c c1,c c2){
	return c1.col==c2.col&&c1.num==c2.num;
}
void judge(){
	sort(poke2,poke2+5);
	int mid[4],mid2[4];
	for(int i = 0;i<4;i++){
		mid[i] = poke2[i+1].num-poke2[i].num;
		mid2[i] = abs(poke2[i+1].col-poke2[i].col);
	}
	if(poke2[0]==poke2[3]||poke2[1]==poke2[4]) ans[1]++;//{ans[1]++;cout<<"//炸弹 "<<endl;} 
	else if((poke2[1] == poke2[3])||(poke2[0] == poke2[2] && poke2[3].num != poke2[4].num)||(poke2[2] == poke2[4] && poke2[0].num != poke2[1].num)) ans[5]++;//{ans[5]++;cout<<"//三条"<<endl;}  
	else if((poke2[0] == poke2[2] && poke2[3] == poke2[4])||(poke2[2] == poke2[4] && poke2[0] == poke2[1])) ans[2]++;//{ans[2]++;cout<<"//三代二"<<endl;} 
	else if(((poke2[0] == poke2[1]) && (poke2[2] == poke2[3]))||((poke2[2] == poke2[1]) && (poke2[4] == poke2[3]))||((poke2[0] == poke2[1]) && (poke2[4] == poke2[3]))) ans[6]++;//{ans[6]++;cout<<"//两对"<<endl;} 
	else if((poke2[0]==poke2[1])||(poke2[1]==poke2[2])||(poke2[2]==poke2[3])||(poke2[3]==poke2[4])) ans[7]++;//{ans[7]++;cout<<"//一对 "<<endl;} 
	else if((mid[0]*mid[1]*mid[2]*mid[3] == 1)&&(mid2[0]+mid2[1]+mid2[2]+mid2[3] == 0)) ans[0]++;//{ans[0]++;cout<<"//同花顺 "<<endl;} 
	else if(mid[0]*mid[1]*mid[2]*mid[3] == 1) ans[4]++;//{ans[4]++;cout<<"//顺子"<<endl;} 
	else if(mid2[0]+mid2[1]+mid2[2]+mid2[3] == 0) ans[3]++;//{ans[3]++;cout<<"//同花"<<endl;} 
	else ans[8]++;//{ans[8]++; cout<<"啥都不是"<<endl;} 
	
}
void solve(){
	for(int i = 0;i<A*B;i++){
		for(int ki=0;ki<2;ki++) poke2[ki] = poke[ki];
		get(i);
		if(same(curr,poke[0])||same(curr,poke[1])) continue;
		poke2[pos++] = curr;
		poke[pos-1] = curr;
		for(int j=i+1;j<A*B;j++){
			for(int ki=0;ki<3;ki++) poke2[ki] = poke[ki];
			get(j);
			if(same(curr,poke[0])||same(curr,poke[1])) continue;
			poke2[pos++] = curr;
			poke[pos-1] = curr;
			for(int k=j+1;k<A*B;k++){
				get(k);
				for(int ki=0;ki<4;ki++) poke2[ki] = poke[ki];
				if(same(curr,poke[0])||same(curr,poke[1])) continue;
				//cout<<i<<" "<<j<<" "<<k<<" \n";
				poke2[pos++] = curr;
				judge();
				aa++;
				pos--;
			}
			pos--;
		}
		pos--;
	}
}

int main(){
	cin>>A>>B;
	init();
	int a1,b1;
	cin>>a1>>b1;
	curr.num = a1;
	curr.col = b1;
	poke[pos++] = curr;
	cin>>a1>>b1;
	curr.num = a1;
	curr.col = b1;
	poke[pos++] = curr;
	solve();
	for(int i = 0;i<9;i++)
		cout<<ans[i]<<" ";
	cout<<endl;
	return 0;
}
### 关于山东大学程序设计 Week5 的课程资料作业 尽管当前提供的引用并未直接提及山东大学程序设计思维实践的第5周具体内容,但从已有参考资料来看,可以推测该课程可能涉及的内容范围以及学习目标。 通常情况下,在类似的程序设计课程中,第五周的学习重点可能围绕以下几个方面展开: #### 可能的主题方向 1. **动态规划基础** 动态规划是一种解决多阶段决策过程最优化问题的方法。它通过将复杂问题分解成更简单的子问题来求解最优解[^2]。如果 Week5 涉及此主题,学生可能会接触到经典的动态规划问题,例如背包问题、最长公共子序列(LCS)、矩阵链乘法等。 2. **贪心算法的应用** 贪心算法的核心在于每一步都做出局部最优的选择,期望最终达到全局最优解。这种策略适用于某些特定场景下的问题,比如活动选择问题、霍夫曼编码等问题[^1]。 3. **图论初步** 图论作为离散数学的重要分支之一,在计算机科学中有广泛的应用价值。Week5 也可能引入基本概念如连通性检测、最小生成树(Kruskal 和 Prim 算法),或者单源最短路径(Dijkstra 算法)[^4]。 4. **高级数据结构介绍** 高级的数据结构能够显著提升解决问题效率。例如堆(Heap)用于实现优先队列;并查集(Union-Find Set)用来处理集合合并操作等等[^3]。 以下是基于上述假设整理的一道典型练习题及其解答思路: --- #### 练习题示例:最大连续子数组和 给定一个整数数组 `nums` ,找到其中具有最大和的一个连续子数组,并返回其总和。 ##### 思路分析: 采用 Kadane's Algorithm 来高效完成任务。核心思想是在遍历过程中维护两个变量——当前的最大子数组结束位置处的累加值(`current_sum`)以及迄今为止发现的整体最大值(`max_so_far`)。每当遇到新的元素时更新这两个量即可得出答案。 ```python def maxSubArray(nums): current_sum = nums[0] max_so_far = nums[0] for i in range(1, len(nums)): # 判断是否应该重新开始一个新的子数组还是延续之前的 current_sum = max(nums[i], current_sum + nums[i]) # 更新整体最大值 max_so_far = max(max_so_far, current_sum) return max_so_far ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值