第一部分:二分查找
假设给出若干个(可以很多)有序的整数,请查找某个元素是否存在,比如——
2 3 4 5 6 8 12 20 32 45 65 74 86 95 100
请查找以上数列中是否存在某个整数(比如25),若有,请输出其位置,否则请输出NO~
二分查找的前提—— 数据的单调性
时间复杂度:O(logN)
例题:HDOJ-2199
地址:http://acm.hdu.edu.cn/showproblem.php?pid=2199
代码:
#include
#include
#include
#include
#include
#define Y(x) 8*x*x*x*x+7*x*x*x+2*x*x+3*x+6-y
using namespace std;
int n, m;
int sum;
int main()
{
double s = 0, e = 100, y;
int t;
cin>>t;
while(t--)
{
s = 0;
e = 100;
cin>>y;
if(Y(e)>=0&&Y(s)<=0)
{
while(e-s>1e-6)
{
if(Y((s+e)/2)>1e-10)
e = (s+e)/2 - 1e-7;
else
s = (s+e)/2 + 1e-7;
}
printf("%.4lf\n", (s+e)/2);
}
else
cout<<"No solution!"<
地址:http://acm.hdu.edu.cn/showproblem.php?pid=2899
思考:非一般的查找原函数零点,而是搜寻最值。即查询导函数的零点~
代码:
#include
#include
#include
#include
#include
#define AY(x) 6*pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*x*x-y*x
#define CY(x) 42*pow(x,6)+48*pow(x,5)+21*pow(x,2)+10*x-y
using namespace std;
int n, m;
int sum;
int main()
{
double s, e, y;
int t;
cin>>t;
while(t--)
{
s = 0;
e = 100;
cin>>y;
while(e-s>1e-6)
{
if(CY((s+e)/2)>1e-10)
e = (s+e)/2 - 1e-7;
else
s = (s+e)/2 + 1e-7;
}
printf("%.4lf\n", AY((s+e)/2));
}
}
三分查找,略
#include
#include
#include
#include
#include
using namespace std;
char s[9][9];
int n, m, d1, d2, t;
int me[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool escape;
int dfs(int s1, int s2, int cnt)
{
int i, temp;
if(escape)
return 0;//已经符合条件,退出
if(s1>n||s2>m||s1<=0||s2<=0)//越界,退出
return 0;
if(cnt==t&&s1==d1&&s2==d2)
escape = 1;
temp=(t-cnt)-abs(s1-d1)-abs(s2-d2);
if(temp<0||temp%2)//剪枝一
return 0;
for(i=0;i<4;i++)
{
if(s[s1+me[i][0]][s2+me[i][1]]!='X')
{
s[s1+me[i][0]][s2+me[i][1]]='X';//表示已走过
dfs(s1+me[i][0],s2+me[i][1],cnt+1);
s[s1+me[i][0]][s2+me[i][1]]='.';//复原
}
}
return 0;
}
int main()
{
int i, j, wall;
int s1, s2;
while(cin>>n>>m>>t,n+m+t)
{
escape = 0;
memset(s,'X',81*sizeof(char));
wall = 0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>s[i][j];
if(s[i][j]=='S')
{
s1=i;
s2=j;
}
else if(s[i][j]=='D')
{
d1=i;
d2=j;
}
else if(s[i][j]=='X')
wall++;
}
if(n*m-wall<=t) //剪枝二
{
cout<<"NO"<
嘛, 剪枝要详细点写
剪枝一
那么设所在位置 (s1,s2) 与 目标位置 (d1,d2)
如果abs(d1-s1)+abs(d2-s2) 为偶数,则说明 abs(d1-s1)+和 abs(d2-s2)的奇偶性相同,需要走偶数步.
如果abs(d1-s1)+abs(d2-s2)为奇数,那么说明 abs(d1-s1)和 abs(d2-s2)的奇偶性不同,需要走奇数步.
解为 abs(d1-s1)+abs(d2-s2)的奇偶性就确定了所需要的步数的奇偶性!!
而 (t-cnt)表示剩下还需要走的步数,由于题目要求要在 t时恰好到达,
那么(t-cnt)与abs(d1-s1)+abs(d2-s2) 的奇偶性必须相同
因此 temp=t-cnt- abs(d1-s1)+abs(d2-s2)必然为偶数!
剪枝二
这个比较简单也没什么大用, 约定时刻走过的方块数加上墙的个数应当小于总区域面积。
inline double Y(double x)
{
return SomethingAboutX;
}
const double eps = 1e-6;
double BinSearch(double start, double end, double K )
{
double mid;
if(fabs(Y(start)-K)eps)
{
mid = (start + end)/2 ;
if(Y(mid)-K>eps)
end = mid - eps;
else
start = mid + eps;
}
return (start+end)/2;
}