poj 1948(搜索+剪枝)

本文探讨了解决具有特定约束条件的三角形面积问题的方法,通过引入搜索与剪枝策略,有效地减少了不必要的节点拓展,避免了程序超时。详细介绍了两种优化方法,包括使用mark矩阵来标记已处理的边组合,以及如何通过排序和剪枝来减少搜索空间,最终实现了高效求解。

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

解题思路:这道题看到数据量,想到应该搜索+剪枝应该可以过。。可是别人的A了,我的却超时了。。。

我用了一个mark[a][b],表示前两条边长度分别为a和b时,是否已经处理过,如果是的话就直接跳出。。。剩下的就是一个比较简单的搜索过程了,代码不难写,但是确实超时不可避免。。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn = 45;
int n,len[maxn],s;
double half,ans;
bool vis[maxn],mark[maxn][maxn];

bool cmp(int a,int b)
{
	return a < b;
}

void dfs(int cur,int a,int b,int dep)
{
	if(mark[a][b] || mark[b][a]) return;
	if(dep == 3){
		int c = s - a - b;
		mark[a][b] = mark[b][a] = true;
		if(a + b <= c || b + c <= a || a + c <= b) return;
		double area = half*(half-a)*(half-b)*(half-c);
		if(area > ans) ans = area;
		return;
	}
	for(int i = cur+1; i <= n; i++){
		if(vis[i] == true) continue;
		vis[i] = true;
		if(dep == 1){
			dfs(cur+1,a+len[i],b,dep);
			dfs(0,a+len[i],b,dep+1);
		}
		else{
			dfs(cur+1,a,b+len[i],dep);
			dfs(0,a,b+len[i],dep+1);
		}
		vis[i] = false;
	}
}

int main()
{
	while(scanf("%d",&n)!=EOF){
		s = 0;
		for(int i = 1; i <= n; i++){
			scanf("%d",&len[i]);
			s += len[i];
		}
		half = s / 2.0;
		sort(len+1,len+1+n,cmp);
		memset(vis,false,sizeof(vis));
		memset(mark,false,sizeof(mark));
		ans = -1;
		dfs(0,0,0,1);
		if(ans < 0) printf("-1\n");
		else printf("%d\n",(int)(sqrt(ans)*100));
	}
	return 0;
}



看了下别人的剪枝,确实比我拓展的节点要少,同样mark[i][a][b]表示第i条边时,最短边为a,次短边为b时,是否处理过。。。因为我自己写的mark[a][b]可能会出现重复的情况,因为a,b,c的大小关系并没有确定好,相同的三角形可能会出现三次,这样拓展出的新节点个数太多,会导致超时的。。。


#include <iostream>
#include <cmath>

using namespace std;

const int MAXN = 41;
int fence[MAXN];
bool mark[MAXN][MAXN * MAXN][MAXN * MAXN];

int N, s;

double hs;

void recur(int i, int a, int b, double &maxt)
{
	if(a > s / 3 || mark[i][a][b])
	{
		return;
	}
	mark[i][a][b] = true;
	
	if(i == N)
	{
		int c = s - a - b;
		if(a > 0 && b > 0 && c > 0 && a <= b && b <= c && a + b > c)
		{
			double t = (hs - a) * (hs - b) * (hs - c);
			if(t > maxt)
			{
				maxt = t;
			}

		}
		return;
	}

	recur(i + 1, a + fence[i], b, maxt);
	recur(i + 1, a, b + fence[i], maxt);
	recur(i + 1, a, b, maxt);
}

int main()
{
	cin>>N;
	s = 0;
	for(int i = 0; i < N; ++i)
	{
		cin>>fence[i];
		s += fence[i];
	}
	hs = s * 1.0 / 2;
	double maxt = -1;
	recur(0, 0, 0, maxt);
	if(maxt < 0)
	{
		cout<<"-1"<<endl;
	}
	else
	{
		cout<<(int)(sqrt(maxt * hs) * 100)<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值