洛谷 2-12递推递归二分

台阶问题
n,k 台阶每次最多可以跨k层,最少1层,问到第n个台阶的方案数
很明显,到第n个台阶的方案数,就是到前面所有的n-k个台阶的 方案数之和。
题目有要求取模,那就每次求得并取模。
复杂度 nk,题目数据 n≤100000,K≤100,还可以凑合

#include
using namespace std;
const int MOD=100003;
const int maxn=100005;

int a[maxn]={0};
int main()
{
    int n,k;
    cin>>n>>k;
    a[0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=k;j++)
        {
            if(i-j<0)break;
            a[i]+=a[i-j];
            a[i]%=MOD;
        }
    }
    cout<

数的划分
n,k,问将n划分为k个数相加的方案数(组合数)
抽象为小球问题:
一共n个小球,放到k个桶里,放法有哪些?
1.至少有一个桶里有一个球;
2.每个桶都不止一个球;
两种情况相加,就是所有的方案。
对于1:那问题就和 【n-1个球放到k-1个桶里】 等价
对于2:每个桶都不知一个球,那我把每个桶都拿走一个球,之和再放回去就行
那问题就和 【把n-k个球放到k个桶里】等价
于是我们就定义,a[n][k]为n个球放入k个桶里的方案数
我们从小到大 递推即可。

#include
using namespace std;
int n,k,f[201][7]={0};  //f[k][x] k 分成 x 份 ={f[k-1][x-1],f[k-x][x]}
int main()
{
    cin >> n >> k;
    for(int i=1;i<=n;i++)
    {
        f[i][1]=1;
        f[i][0]=1;
    }
    for(int i=2;i<=n;i++)
    {
        for (int x=2;x<=k;x++)
        {
            if (i>x) f[i][x]=f[i-1][x-1]+f[i-x][x];
            else f[i][x]=f[i-1][x-1];
        }
    }
    cout<

传球游戏
n个人围一圈,开始球在1号手里,问经过m次传球,回到1号手中的方案数。球只能给相邻的两个人。
所以我们定义数组 a[i][k]表示 第i个人在第k次传球得到球的方案数
第i个人,[1-n] 一般的a[i][k]=第k-1次 球在左边那个人+ 球在右边那个人手中 的方案数
即: a[i][k]=a[i-1][k-1]+a[i+1][k-1],在1和n号 处理一下。
我们已知起始是在1号手里的,于是a[1][0]=1;

#include
using namespace std;
const int maxn=33;

int a[maxn][maxn]={0};
int main()
{
    int n,m;
    cin>>n>>m;
    a[1][0]=1;

    for(int k=1;k<=m;k++)
    {
        a[1][k]=a[2][k-1]+a[n][k-1];
        for(int i=2;i

奇怪的电梯
第i层电梯只可以向上或者向下ki,所到层数要求合法,否则不让去。
一共n层,问从A层到B层,最少需要乘坐电梯的次数。
思路:bfs 去过的楼层标记一下,不要重复去

#include
using namespace std;

int a[205],vis[205];
int n,A,B;
struct node
{
    int lev,step;
}s,now;
int bfs()
{
    queueq;
    s.lev=A,s.step=0;
    vis[A]=1;
    q.push(s);

    while(!q.empty())
    {
        now=q.front();q.pop();
        if(now.lev==B)
        {
            cout<=1)
        {
            s.lev=levv-a[levv];
            s.step=now.step+1;
            if(!vis[s.lev]) 
            {
                vis[s.lev]=1;
                q.push(s);  
            }
        }
    }
    return -1;
}
int main()
{
    cin>>n>>A>>B;
    for(int i=1;i<=n;i++) cin>>a[i];
    memset(vis,0,sizeof(vis));
    if(bfs()==-1) cout<<"-1";
}

数字三角形
给出n和一个n层的三角形,找出一条路径,使得和最大。每个点只能向左下或者向右下 走。
思路:从下往上 将较大的那个数加上去,依次递推

#include
using namespace std;
const int maxn=1005;
int a[maxn][maxn]={0};
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cin>>a[i][j];
        }
    }
    for(int i=n-1;i>=1;i--)
    {
        for(int j=1;j<=i;j++)
        {
            a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
        }
    }
    cout<

数列分段
将数列分为m段,求最小的 每段的和的最大值。
思路:二分+贪心

#include
using namespace std;
const int maxn=100005;
int n,m,a[maxn];
int l,r=0,mid;
inline bool checkk(int x)//将数列分为每段和都<=x
{
    int ans=0,num=0;//ans为该段和,num为段数
    for(int i=1;i<=n;i++)
    {
        if(ans+a[i]<=x) ans+=a[i];
        else ans=a[i],num++;
    }
    return num>=m;//如果段数多于题目要求,就在区间右边继续找
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)//答案必在 max(a[i])与sum(a[i])直接,二分找答案
    {
        cin>>a[i];
        l=max(l,a[i]);
        r+=a[i];
    }
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(checkk(mid))l=mid+1;
        else r=mid-1;
    }
    cout<

丢瓶盖
地上丢了A个瓶盖,为了简化问题,我们可以当作这A个瓶盖丢在一条直线上,现在他想从这些瓶盖里找出B个,使得距离最近的2个距离最大,他想知道,最大可以到多少呢?

分析:最小值最大化问题->二分求答案:二分区间l=0,r=最远的两个瓶盖距离
最近的两个瓶盖距离为d,则满足该取法的 其他任意两个瓶盖距离>=A[pos]+d //pos为上一个满足条件的位置。我们最左端的瓶盖开始取。

#include
using namespace std;
const int maxn=100005;
int n,m,a[maxn];
int l,r,mid;
inline bool checkk(int x)//间距为x
{
    int pos=a[1]+x,num=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>=pos)
        {
            pos=a[i]+x;
            num++;
        }
    }
    return num>=m;//如果可取瓶盖数多于题目要求,就在区间右边继续找
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+1+n);
    l=0,r=a[n]-a[1];
    int ans=0;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(checkk(mid))l=mid+1,ans=max(ans,mid);
        else r=mid-1;
    }
    cout<

你可能感兴趣的:(ACM)