木棍游戏(二进制枚举)

题目链接:link

题目大意:

给出 n 根长度不一的木棍,第 i 根棍子长度为 a i a_i ai 。两根长度分别为 a b 和 a c a_b 和 a_c abac的木棍可以拼接成一根长度为 a b + a c a_b+a_c ab+ac 的木棍,同理 3 根,4 根,甚至 n 根都能拼接。
问:使用这 n 根木棍作三角形的边(一根木棍至多使用一次,也可以不使用),能拼出的面积最大的三角形的面积。

解题思路:

通过数据范围可知 n 最大为 8 ,所以我们可以用二进制枚举来枚举每一条边是由那些木棍组成。复杂度O ( ( 1 < < n ) 3 ) ((1<<n)^3) ((1<<n)3)

AC代码:

#include <bits/stdc++.h>
using namespace std;
int a[10], n;
double cal(int x) //将选中的木棍长度加起来
{
	double ans = 0;
	for (int i = 0; i < n; i++)
	{
		if (x >> i & 1) ans += a[i];
	}
	return ans;
}
bool check(double a, double b, double c) //判断a,b,c三条边是否能够组成三角形
{
	if (a > b) swap(a, b);
	if (a > c) swap(a, c);
	if (b > a) swap(b, c);
	return a + b > c;
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++) cin >> a[i];
	double ans = -1;
	for (int i = 0; i < (1 << n); i++) //枚举第一条边
	{
		double A = cal(i);
		for (int j = 0; j < (1 << n); j++) //枚举第二条边
		{
			if (i & j) continue; //判断是否重复选用木棍
			double B = cal(j);
			for (int k = 0; k < (1 << n); k++) //枚举第三条边
			{
				if (i & k || j & k) continue; //判断是否重复选用木棍
				double C = cal(k);
				if (check(A, B, C))
				{
					double p = (A + B + C) / 2;
					ans = max(ans, sqrt(p * (p - A) * (p - B) * (p - C)));
				}
			}
		}
	}
	if (ans < 0) puts("-1");
	else printf("%.1f\n", ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A:木棍还原问是一种常见的深度优先算法。具体的思路是,先将破碎的木棍抽象成一个图形,然后从任意一根木棍开始,以逆时针的顺序将其端点遍历,并将遍历过的木棍断开,变成两根更短的木棍。然后从任意一条与当前木棍相邻的木棍再次开始遍历,直到所有的木棍都被拼接完成或者无法拼接。 具体步骤如下: 1. 选择一根木棍,从其中任意一端开始遍历它的邻接木棍。 2. 对于每个邻接木棍,重复1,直到所有邻接木棍被遍历过。 3. 如果当前木棍的两端都没有邻接木棍,则将其标记为已经访问,从当前栈中弹出并返回上一级调用。 4. 否则,选择一个未曾遍历的邻接木棍,将其作为当前木棍,将其标记为已访问并进入栈中,从1开始。 在实现深度优先算法时,需要注意以下几点: 1. 应该使用栈来维护当前遍历路径。 2. 应该记录每个木棍是否已经访问过,避免重复访问。 3. 应该检测当前木棍的邻接木棍是否能够拼接,如果不能,应该回溯到上一个节点尝试其他路径。 代码示例: ``` def dfs(stick, path): if len(path) == len(stick): # 所有木棍已经还原完成 return True for i in range(len(stick)): if not visited[i]: # 当前木棍未被访问 visited[i] = True path.append(stick[i]) for j in range(i+1, len(stick)): if not visited[j] and sum(path) + stick[i] + stick[j] <= total_length: visited[j] = True path.append(stick[j]) if sum(path) == total_length: # 可以完成拼接 return True if dfs(stick, path): # 搜索下一级节点 return True path.pop() visited[j] = False path.pop() visited[i] = False return False ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值