首页 > 其他分享 >poj 1948(搜索+剪枝)

poj 1948(搜索+剪枝)

时间:2023-05-29 19:34:56浏览次数:63  
标签:剪枝 1948 return int maxt mark poj MAXN include


解题思路:这道题看到数据量,想到应该搜索+剪枝应该可以过。。可是别人的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;
}




标签:剪枝,1948,return,int,maxt,mark,poj,MAXN,include
From: https://blog.51cto.com/u_16143128/6373664

相关文章

  • poj 1604
    题意:计算n!最后一位不为0的数解题思路:1*2*3*......*n,每次乘完一个数后,把末尾0去掉,然后模上一个数,这样算出来的数肯定是最后一位不为0的数。。注意这里模的数不能太小,同时也不能太大,太小可能会影响乘积的效果,譬如可能出现0的情况被之前的模运算给抹掉了,太大就直接溢出了。。。参考了......
  • poj 2078(搜索+剪枝)
    解题思路:可以一行一行地递归求解,要是不符合条件就回溯,注意最后一行不能够移动它,因为可能会与之前重叠。。#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintmaxn=8;intn,mat[maxn][maxn],ans;intget_max(intdep){ intm=......
  • poj 1324(BFS+状态压缩)
    解题思路:这道题一开始的想法就是状态压缩,即考虑如何判重,由于蛇并非是直线的,所以想到了以每一个点的上下左右共四个值来表示相对位置。最开始想如何用四进制来表示它,无语。。。。。还是题目做少了,直接用两位来表示一个点即可(两位的二进制数可以表示0-3)。剩下的关键就是判断蛇头会不......
  • poj 1195(二维树状数组)
    解题思路:这是一道很裸的二维树状数组AC:#include<stdio.h>#include<string.h>#defineN1100intc[N][N],n,arr[N][N];intlowbit(intx){returnx&(-x);}voidupdate(intx,inty,intnum){inti,j;for(i=x;i<=n;i+=lowbit(i))for(j=y;......
  • POJ 1505(二分+贪心)
    题意:给一些书,这些书有不同的页数,让把这些书分成k份,必须是连续的,问这些份中页数和的最大值最小是多少。解题思路:知道了页数和的范围,而且书都是连续的,要找到页数和最大值的最小值可以直接二分答案。。AC:#include<iostream>#include<cstdlib>#include<cstring>usingnamespacestd......
  • poj 3411(DFS多点访问)
    题意:有n座城市和m(1<=n,m<=10)条路。现在要从城市1到城市n。有些路是要收费的,从a城市到b城市,如果之前到过c城市,那么只要付P的钱,如果没有去过就付R的钱。求的是最少要花多少钱。解题思路:这道题的n与m都很小,dfs可以搞定,但这里与以往的搜索不同,以前dfs每个节点只能够访问一次,这里有多次访......
  • POJ 1797 Heavy Transportation(迪杰斯特拉最短路变形)
    传送门题意分析:Hugo想要扩展他的公司,他有起重机要到目的地,到达目的地有很多条路径,但是,每一条路都有相应承重量,现在需要找出到达目的地的最大承重道路的承重质量。解题分析:首先,每一条路径的承重量取决于承重量最小的那条道路(短板效应),所以就是找所有路径的最小值,然后选择最小值最大的......
  • POJ 1753 Flip Game(枚举+递归)
    传送门思路是别人的,自己理解了半天,真是渣渣。对于自己,路还长,年轻人。对任意一个格子来说,翻动偶数次等于没翻,翻动奇数次等于翻一次,所以只需考虑翻一次的情况。一共16个格子,每个格子只有翻和不翻,所以最多16步,最少0步,题目要求最少的步数,所以0——>16枚举,看哪一步先成功就是最优解。使......
  • POJ 3069 Saruman's Army(贪心)
    传送门这个题是说给你n个点,然后让你标记其中尽可能少的点,使得n个点都处于被标记点左右不超过R的区间内我们使用的是贪心算法,也就是我们要将被标记的点尽可能的朝右边去即可,首先我们将他们从左到右进行排序,第一个我们所选取的被标记的点应该是能够包含掉左边的点的最靠右的点。。。......
  • POJ 1182 食物链
    解题思路:并查集经典中的经典题,在网上看了很多大牛的思路,大部分是增加一个结构体存动物间的关系,结合并查集判断,但是关系域的更新比较复杂,一下子不太容易理解。所以就有人另开思路,这里介绍一个十分巧妙的思路。一般我们都会把一个动物当成一个节点,然后去执行并查集等操作。但是有位大......