今天讲递推和二分。递推我还勉强听懂了,但我二分听得迷迷糊糊的。所以二分的题刷的很少。我的二分不会灵活运用,对它的理解是最基础的在一串有序序列中用二分查找一个数的理解。
递推是从已知到未知求解。递推我只敲了几道基本模板题。
第一题:取数问题。从1~n中取走任意个数,但不能同时取相邻两个数,问有几种取法。
#include<bits/stdc++.h>
using namespace std;
int n;
long long a[110]={};
int main()
{
cin>>n;
a[1]=2; a[2]=3;
for(int i=3;i<=n;i++)
a[i]=a[i-1]+a[i-2];//可以不取i,那么可以取(i-1)个数的方法,可以取i,那么不可以取i-1所以可以取(i-2)个数的方法,
cout<<a[n];
}
第二题:有1*n的长方形,可以用1*1,1*2,1*3的方形覆盖,问有几种覆盖方法。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
long long a[110]={};
cin>>n;
a[1]=1;a[2]=2;a[3]=4;
for(int i=4;i<=n;i++)
a[i]=a[i-1]+a[i-2]+a[i-3];//可以用1*1的方形覆盖,那么还剩i-1个方格。可以用1*2的方形覆盖,那么还剩i-2个方格。可以用1*3的方形覆盖,那么还剩i-3个方格
cout<<a[n];
return 0;
二分是分治的一种,主要是算最大的最小或最小的最大
第三题:人们从起点走过石头到终点,有人把石头拿走了m个问最短石头到石头距离的最大值
#include<bits/stdc++.h>
using namespace std;
int s,n,m,z,L,R;
int a[51000]={};
int h(int x)
{
int y=1,l=0;
for(int i=2;i<=n+1;i++)
{
if(a[i]-a[y]<x)
l++;
else y=i;
}
if(l<=m)
return 1;
else return 0;
}
int main()
{
cin>>s>>n>>m;
a[1]=0;
for(int i=1;i<=n;i++)
cin>>a[i+1];
a[n+2]=s;
L=0; R=s;
while(L+1<R)//二分
{
z=(L+R)/2;
if(h(z)==1)
L=z;
else
R=z;
}
if(h(R)==1)
cout<<R;
else cout<<L;
}
}