XJOJ 105 扫雷

 

这题是一个回溯题。http://202.117.21.117/xjoj/problem_html/105.html

前后一共交了3个版本,分别把时间从 1312ms 改到了 16ms。

 

 

ID:TIME:NAME:TASK:LANGUAGE:STATUS:CASE:TIME:MEMORY:
261302011-05-26 00:50:50ysg860607105g++Accepted1016MS320KB
261292011-05-26 00:48:42ysg860607105g++Wrong Answer34MS320KB
261282011-05-26 00:44:07ysg860607105g++Accepted10308MS320KB
261272011-05-26 00:39:15ysg860607105g++Accepted10792MS344KB


其实就是对回溯算法进行剪枝,逐步去掉很多无谓的计算。

第一个版本,即id = 26127

 

#include "stdio.h"

int numbers[10001];
bool bombs[10001];

 

int N=0;
int methods=0;

inline bool preCondition(int step)
{
	for(int i=0;i<step-1;i++)
		if(numbers[i]!=0)
			return false;
	return true;		
}
inline bool isFinish()
{
	for(int i=0;i<N;i++)
		if(numbers[i]!=0)
			return false;
	return true;
}
inline void set(int step)
{
	bombs[step] = true;
	if(step > 0)
		numbers[step-1]--;
	numbers[step]--;
	if(step < N-1)
		numbers[step+1]--;
}
inline void reset(int step)
{
	bombs[step] = false;
	if(step > 0)
		numbers[step-1]++;
	numbers[step]++;
	if(step < N-1)
		numbers[step+1]++;
}
inline void search(int step)
{
	if(isFinish())
	{
		methods++;
#if 0
		cout << "Solution No."<< methods <<":" << endl;
		for(int i=0;i<N;i++)
			cout << bombs[i] <<',';
		cout << '/b'<< endl;
#endif
		return ;
	}
	for(int i=step;i<N;i++)
	{
		if(preCondition(i))
		{		
			set(i);
			search(i + 1);
			reset(i);
		}else
			return;
	}
}
inline void solve(int num[],int N)
{
	for(int i=0;i<N;i++)
		bombs[i] = 0;
	search(0);
}
int main()
{
	scanf("%d",&N);
	for(int i=0;i<N;i++)
		scanf("%d",&numbers[i]);
	solve(numbers,N);
	printf("%d",methods);
	return 0;
}

接下来,分别对两个条件判断函数进行了优化,去掉了不必要的判断。

 

inline bool preCondition(int step)
{
	if(step > 1 && numbers[step-2] !=0)
		return false;
	return true;		
}
inline bool isFinish(int step)
{
	int i = 0;
	if(step > 2)
		i = step - 2;
	for(;i<N;i++)
		if(numbers[i]!=0)
			return false;
	return true;
}

 

然后时间就一下子减少到16ms了。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值