洛谷P1433 吃奶酪 记忆化+启发式搜索

吃奶酪这道题,本来数据很小,但由于洛谷管理员大大的加强,

成功地卡掉了题解排名第一的DFS做法。

呵呵呵说好的裸搜索题,搜索做法被掉了是几个意思

我也是在写了一个DFS发现被卡之后来翻题解,

然后发现排名第一的题解做法不是和我一模一样吗?

copy下来放下本地跑10的数据,

发现跑了8秒。。。

才发现貌似是题解的问题。

下次麻烦管理员大大更毒瘤数据时,更新一下题解好不

然后翻了翻题解,发现都是时间都很远古,

也就是说所有的dfs做法貌似都跑不过。。。

扫描二维码关注公众号,回复: 10308427 查看本文章

那请问为何要放在搜索的题单里,

而不是dp里?


不过我堂堂天朝OIer,怎可放弃DFS爆搜?

于是本人苦心研究,终于做出了启发式搜索的做法。


注意:

启发式搜索并非正解


因为数据

毒瘤

那我们做题人就得

更毒瘤!


充分发挥我天朝OIer面向数据编程的传统美德

可以用memory(顾名思义)的一个二维数组存储

第一位表示点i,第二维表示步数step,

存储什么呢?

存储最短的距离,

如果后来访问到这个点,

就将当前已经走的距离同这个数组里存储的最短距离进行比较,

如果小于就更新,大于就return


我们发现,这是记忆化+贪心思想,

但是这个记忆化贪心并非是对的,

以为每一步的抉择具有后效性

也许你走step步到i点的最短距离是正确的,

但并不能保证走step+1步到i+1(也可以是其他点)的最短路径就是memory[i][step]+distance[i][i+1]

那怎么办呢?(此时教练可能会提醒你用动态规划了,转dp正解)

但我就是想用DFS怎么办呢?

那就该请出我们今天的主角了——启发式搜索,

简单来说,启发式搜索就是对取和不取都做分析,从中选取更优解(或删去无效解)

代码的关键就是这么一行:

	if(s<memory[i][step]+s2)
	{
		memory[i][step]=s;
	}

这里的s2取什么呢?

因为我谷可下载未通过测试的数据点,

故经过一番思考(胡搞)后

可发现s2取sqrt(0.8)可通过所有测试点

(s2的取值视情况而定,追求速度可以往小取。追求稳妥可以往大取)

并且整个程序跑得飞快——53ms

甚至超越了dp正解的171ms

我拒绝和数据改造之前的记录对比

奉上AC代码

#include<bits/stdc++.h>
using namespace std;
int N;
struct pue
{
	double a,b;
}; 
pue w[22];
double ans=INT_MAX;
double distance[30][35];
double memory[30][30];
bool vis[25];
double s2=sqrt(0.8);
double calculate(double x1,double y1,double x2,double y2)
{
	double ke=x1-x2,kr=y1-y2;
	return sqrt(ke*ke+kr*kr);
}
void yuchuli()
{
	for(int i=0;i<=N;i++)
	for(int j=0;j<=N;j++)
	{
		memory[i][j]=INT_MAX;
		distance[i][j]=calculate(w[i].a,w[i].b,w[j].a,w[j].b);
	}
}
void dfs(double s,int i,int step)
{
	if(s<memory[i][step]+s2)
	{
		memory[i][step]=s;
	}
	else
	return ;
	if(step==N)
	{
	if(ans>s)ans=s;
	return ;	
	}
	for(int j=1;j<=N;j++)
	{
		if(i==j)continue;
		if(vis[j]==0)
		{
		double k=s+distance[i][j];
		if(k<ans)
		{
			vis[j]=1;
			dfs(k,j,step+1);
			vis[j]=0;
		}
		}
		
		
	}
}
bool com(pue x,pue y)
{
	if(x.a!=y.a)return x.a>y.a;
	else
	return x.b>y.b;
}
int main()
{
	scanf("%d",&N);
	for(int i=1;i<=N;i++)
	{
		scanf("%lf%lf",&w[i].a,&w[i].b);
	}
	sort(w+1,w+1+N,com);//这里需要从大到小进行排序
	yuchuli();
	dfs(0.0,0,0);
	printf("%.2f",ans);
    return 0;
}

再次重申,这不是正解!!!

正确性完全经由数据范围而定,

出题人只要换一下大数据,也许就能卡掉,

(不过可以试试s2取其它数)

只是觉得既然是个搜索题,就一定要有搜索的解法,不然怎么对得起题目呢?

同时,也告诉大家,有时使用启发式搜索在考场上打深搜暴力有奇效。

希望大家能有所收获。

如果觉得作者写的还行,就点个赞吧!


猜你喜欢

转载自www.cnblogs.com/poised/p/12597794.html