3.29~4.5遞迴
阿新 • • 發佈:2018-12-08
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次敲過