版权声明: https://blog.csdn.net/zjh_2017/article/details/79829453
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次敲过