这题是一个回溯题。http://202.117.21.117/xjoj/problem_html/105.html
前后一共交了3个版本,分别把时间从 1312ms 改到了 16ms。
ID: | TIME: | NAME: | TASK: | LANGUAGE: | STATUS: | CASE: | TIME: | MEMORY: |
26130 | 2011-05-26 00:50:50 | ysg860607 | 105 | g++ | Accepted | 10 | 16MS | 320KB |
26129 | 2011-05-26 00:48:42 | ysg860607 | 105 | g++ | Wrong Answer | 3 | 4MS | 320KB |
26128 | 2011-05-26 00:44:07 | ysg860607 | 105 | g++ | Accepted | 10 | 308MS | 320KB |
26127 | 2011-05-26 00:39:15 | ysg860607 | 105 | g++ | Accepted | 10 | 792MS | 344KB |
其实就是对回溯算法进行剪枝,逐步去掉很多无谓的计算。
第一个版本,即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了。