1. 程式人生 > >3.29~4.5遞迴

3.29~4.5遞迴

T1拍賣

此題很基本,遞迴式只要考慮兩種情況,是-a還是-b。

#include<bits/stdc++.h>
using namespace std;
long long w,p,a,b,f[1000010];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3
)+(num<<1)+c-48; return num*flag; } long long dfs(long long k) { if (f[k]>=0) return f[k];//記憶化搜尋 if (k<p) return 0;//越界 if (k==p) return 1;//邊界 return f[k]=dfs(k-a)+dfs(k-b); } int main() { w=read(); p=read(); a=read(); b=read(); memset(f,-1,sizeof(f)); f[p]=1
; printf("%lld\n",dfs(w)); return 0; }

T2傳球遊戲

此題也比較基本,遞迴式也只考慮兩種情況,是傳給左邊的人還是右邊的人。但是要加兩個特判,因為它是一個環。

#include<bits/stdc++.h>
using namespace std;
long long n,m,f[50][50];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-'
) flag=-1; for (;c>='0'&&c<='9';c=getchar()) num=(num<<3)+(num<<1)+c-48; return num*flag; } long long dfs(long long k,long long t) { if (f[k][t]>=0) return f[k][t];//記憶化搜尋 if (t==0) { if (k==1) return 1;//邊界 return 0; } if (k==1) return f[k][t]=dfs(2,t-1)+dfs(n,t-1);//特判 if (k==n) return f[k][t]=dfs(1,t-1)+dfs(n-1,t-1);//特判 return f[k][t]=dfs(k-1,t-1)+dfs(k+1,t-1); } int main() { n=read(); m=read(); memset(f,-1,sizeof(f)); f[1][0]=1; printf("%lld\n",dfs(1,m)); return 0; }

T3超級書架

此題考慮第t+1頭奶牛選還是不選,遞迴呼叫身高累加和。

#include<bits/stdc++.h>
using namespace std;
const long long maxn=2000000000;
long long n,b,a[50];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3)+(num<<1)+c-48;
    return num*flag;
}
long long dfs(long long k,long long t)
{
    if (k>=b) return k;//邊界
    if (t==n) return maxn;//邊界
    return min(dfs(k,t+1),dfs(k+a[t+1],t+1));
}
int main()
{
    n=read();
    b=read();
    for (int i=1;i<=n;++i)
    a[i]=read();
    printf("%lld\n",dfs(0,0)-b);
    return 0;
}

T4集合劃分問題

這個遞迴也有點迷,不過後來看了題解還能理解。dfs(x-1,y-1)表示把當前數單獨分在一個集合,y*dfs(x-1,y)表示把當前數加入其它的一個集合中,但是有y種情況,所以要*y。

#include<bits/stdc++.h>
using namespace std;
long long n,m,f[1010][1010];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3)+(num<<1)+c-48;
    return num*flag;
}
long long dfs(long long x,long long y)
{
    if (f[x][y]>=0) return f[x][y];//記憶化搜尋
    if (x==1||y==1||x==y) return 1;//邊界
    if (x<y) return 0;//越界
    return f[x][y]=dfs(x-1,y-1)+y*dfs(x-1,y);
}
int main()
{
    n=read();
    m=read();
    memset(f,-1,sizeof(f));
    f[1][1]=1;
    printf("%lld\n",dfs(n,m));
    return 0;
}

T5倒牛奶

此題真的是要考慮——大的6種情況(a->b a->c b->a b->c c->a c->b),每種大的又有小的2種情況(被灌桶裝滿或原桶空了)。然後打得仔細一點就好啦。

#include<bits/stdc++.h>
using namespace std;
long long a,b,c,sum;
bool d[50],f[50][50][50];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3)+(num<<1)+c-48;
    return num*flag;
}
void dfs(long long x,long long y,long long z)
{
    if (f[x][y][z]) return;//記憶化搜尋
    f[x][y][z]=true;
    if (x>0&&y<b)
    {
        if (x>=b-y) dfs(x-(b-y),b,z);
        else dfs(0,y+x,z);
    }
    if (x>0&&z<c)
    {
        if (x>=c-z) dfs(x-(c-z),y,c);
        else dfs(0,y,z+x);
    }
    if (y>0&&x<a)
    {
        if (y>=a-x) dfs(a,y-(a-x),z);
        else dfs(x+y,0,z);
    }
    if (y>0&&z<c)
    {
        if (y>=c-z) dfs(x,y-(c-z),c);
        else dfs(x,0,z+y);
    }
    if (z>0&&x<a)
    {
        if (z>=a-x) dfs(a,y,z-(a-x));
        else dfs(x+z,y,0);
    }
    if (z>0&&y<b)
    {
        if (z>=b-y) dfs(x,b,z-(b-y));
        else dfs(x,y+z,0);
    }
    if (x==0) d[z]=true;
}
int main()
{
    a=read();
    b=read();
    c=read(); 
    dfs(0,0,c);
    for (int i=0;i<=20;++i)
    if (d[i]) sum++;
    for (int i=0;i<=20;++i)
    if (d[i])
    {
        sum--;
        if (sum>0) printf("%d ",i);
        else printf("%d\n",i);
    }
    return 0;
}

T6整數劃分

此題至今比較懵逼,我覺得它思維難度有點高,要考慮四種情況,我連最基本的遞迴式都寫不出來。一開始還是用深搜寫的。dfs(x-y,y)表示和為x的累加和中包含最大值y,dfs(x,y-1)表示不包含y。

#include<bits/stdc++.h>
using namespace std;
long long n,f[10][10];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3)+(num<<1)+c-48;
    return num*flag;
}
long long dfs(long long x,long long y)
{
    if (f[x][y]>=0) return f[x][y];//記憶化搜尋
    if (x==1||y==1) return 1;//邊界
    if (x<y) return f[x][y]=dfs(x,x);//越界
    if (x==y) return f[x][y]=dfs(x,y-1)+1;//特判
    return f[x][y]=dfs(x-y,y)+dfs(x,y-1);
}
int main()
{
    n=read();
    memset(f,-1,sizeof(f));
    f[1][1]=1; 
    printf("%lld\n",dfs(n,n));
    return 0;
}

T7 2的冪次方

#include<bits/stdc++.h>
using namespace std;
long long n,a[50];
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3)+(num<<1)+c-48;
    return num*flag;
}
void dfs(long long k)
{
    if (k==0) return;
    if (k==1)
    {
        printf("2(0)");
        return;
    }
    if (k==2)
    {
        printf("2");
        return;
    }
    if (k==3)
    {
        printf("2+2(0)");
        return;
    }
    if (k==4)
    {
        printf("2(2)");
        return;
    }
    int t=1;
    while ((1<<t)<=k) t++;
    printf("2(");
    dfs(t-1);
    printf(")");
    if (k!=(1<<(t-1))) printf("+");
    dfs(k-(1<<(t-1)));
}
int main()
{
    n=read(); 
    dfs(n);
    return 0;
}

T8美國血統

#include<bits/stdc++.h>
using namespace std;
string a,b; 
inline int read()
{
    int num=0,flag=1;
    char c=getchar();
    for (;c<'0'||c>'9';c=getchar())
    if (c=='-') flag=-1;
    for (;c>='0'&&c<='9';c=getchar())
    num=(num<<3)+(num<<1)+c-48;
    return num*flag;
}
void dfs(int l1,int r1,int l2,int r2)
{
    if (l1>r1||l2>r2) return;
    for (int i=l1;i<=r1;++i)
    if (a[i]==b[l2])
    {
        dfs(l1,i-1,l2+1,i-l1+l2);
        dfs(i+1,r1,i-r1+r2+1,r2);
    }
    printf("%c",b[l2]);
}
int main()
{
    getline(cin,a);
    getline(cin,b);
    dfs(0,a.size()-1,0,b.size()-1);
    return 0;
}

T9椰子

毒瘤題。坑。還沒2次敲過