计算Dota2英雄属性的组合个数

本文介绍了一种解决Dota2游戏中英雄属性组合问题的算法。通过将属性转换为数字,利用递归方法计算不同属性组合的数量,适用于英雄拥有的任意数量的属性和属性槽。文章详细解释了解决思路和C代码实现。

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

Dota2英雄属性组合计算问题

写在前面

这个题目是我在做公司招聘笔试题遇到的,当时想用排列组合的方法和公式来做,然而根本没有思路,最后也没有做出来。白白花了不少时间。交卷后又一直在想到底怎么解决,还是想到了一种解决的办法。

问题描述

在游戏Dota2中,某英雄有三种属性:冰、火、雷。同时身上有三个无顺序的属性槽,他可以从三种属性中任意选择三个放入属性槽中,然后通过当前的属性组合召唤技能。每种不同的属性组合都可以召唤出不同的技能,属性的组合是无序的,即冰火雷,冰雷火,火雷冰,火冰雷,雷火冰,雷冰火只算一种组合,因此共有十种组合:
1、冰冰冰
2、冰冰火
3、冰冰雷
4、冰火火
5、冰火雷
6、冰雷雷
7、火火火
8、火火雷
9、火雷雷
10、雷雷雷
现在有一个英雄拥有n种属性,同时身上有m个无顺序的属性槽,则问该英雄可以召唤出多少种不同的技能?
要求输入n和m,输出组合出不同技能的个数
例:
输入:
3 3
输出:
10

解决思路

如果将冰,火,雷依次用数字1,2,3来表示
那么题中组合结果为:
111,112,113,122,123,133,222,223,233,333
将一种组合看做一个整数,通过观察发现这些数的百位<=十位<=各位,并且10组数是从小到大依次排列
另外,112,121,211都是一种组合,123,132,213,231,312,321也都算一种组合。
那么现在自己人为规定组合是有顺序的,将属性用不同的数字表示,那么组合后的第一个数<=第二个数<=第三个数<=···<=第m个数。
这样列出的组合肯定是没有重复的。

接下来就是如何用代码去求组合的个数。
我的想法是用递归来实现,将一个大的问题分成若干个同样的小问题。
首先,m个槽可以分为第一个槽+后面m-1个槽,先确定第一个槽中放什么属性,再确定后面的槽放什么属性。这样只要再处理后面m-1的槽,依次减小要处理的槽的数量。
其次,后一个槽中属性对应的数值必须>=前一个槽中属性对应的数值。有了相应的关系才能方便递归。
最后递归的终止条件就是只剩一个空槽,根据前一个槽中属性的数组,确定最后一个槽中能有几种放法。

递归是需要输入的参数有前一个槽中的属性值,当前还剩的空槽的数值以及属性的最大值。

C代码

#include <stdio.h>
/*递归函数
 *输入参数:
 *i:前一个槽中所放属性值
 *m:当前还剩的空槽的个数
 *n:属性的最大值
 *返回值:当前i和m条件下的组合个数
 */
int process(int i, int m, int n)
{
	if (m == 1)
	{
		return n - i + 1;//递归结束条件
	}
	else
	{
		int k;//当前第一个槽中放的值
		int sum = 0;//用于求和
		//由于第一个槽中可以放的属性值可以有若干个不同的选择,且属性值要>=前一个槽中的属性值,因此用一个循环来累加
		for (k = i; k <= n; k++)
		{
			sum += process(k, m - 1, n);	
		}		
		return sum;
	}
}
int main()
{
	int m,n,result;
	scanf("%d %d",&m,&n);//输入槽的个数与属性的个数
	result=process(1,m,n);
	//计算组合的个数,这里的1是因为第一个槽属性值从1开始,那么假设有前一个槽,那槽中的值为1。
	printf("%d\n",result);//打印输出
	return 0;
}

说在最后

关于代码的正确性,我选了n和m不大的几种情况来进行验证,输出结果正确。若有错误,欢迎只出。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值