洛谷题单 【算法1-4】递推与递归

P1255 数楼梯

思路

斐波那契数列+高精度加

实现

int n,f[5010][5010],len;
void jiafa(int k)//高精加法
{
	for(int i=1; i<=len; i++)//两数相加
	    f[k][i]=f[k-1][i]+f[k-2][i];
	for(int i=1; i<=len; i++)//进位
		if(f[k][i]>=10)
		{
			f[k][i+1]+=f[k][i]/10;
			f[k][i]%=10;
			if(f[k][len+1]>0)len++;
		}
}
int main()
{
	cin>>n;
	len=1;
	f[1][1]=1;//预处理
	f[2][1]=2;//预处理
	for(int i=3; i<=n; i++)//开始计算
	    jiafa(i);
	for(int i=len; i>=1; i--)//输出
	    cout<<f[n][i];
	return 0;
}

P1002 [NOIP2002 普及组] 过河卒

思路

本题中马的位置是固定不动的,用一个全0数组来记录整个地图,将马的控制点全部标记为1也就是不能走的。用一个简单的动态规划(可以叫做递推(?))即可

实现

#include <bits/stdc++.h>
using namespace std;
long long a,b,n,m,x[23][23],ma[23][23];
void work(long long x,long long y){
    ma[x][y]=1;
    ma[x-1][y-2]=1;
    ma[x-2][y-1]=1;
    ma[x-2][y+1]=1;
    ma[x-1][y+2]=1;
    ma[x+1][y-2]=1;
    ma[x+2][y-1]=1;
    ma[x+2][y+1]=1;
    ma[x+1][y+2]=1;
}
int main(){
    scanf("%lld %lld %lld %lld",&n,&m,&a,&b);
    a++;
    b++;
    n++;
    m++;
    work(a,b);
    x[1][1]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
        	if(i==1&&j==1)continue;
        	if(ma[i][j]==0)x[i][j]=x[i-1][j]+x[i][j-1];
        }
    }
    printf("%lld",x[n][m]);
    return 0;
}

P1044 [NOIP2003 普及组] 栈

思路

比较容易卡住的一步是明确dp数组的定义: f [ i ] [ j ] f[i][j] f[i][j],i表示栈内数字的个数,j表示未进栈数字的个数,f记录当前状态下有几种情况。
状态转移有两种情况,一种是i==0,栈内没有东西,那么 f [ i ] [ j ] f[i][j] f[i][j] = f [ i + 1 ] [ j − 1 ] f[i+1][j-1] f[i+1][j1]也就是该状态只能由某一个状态pop一个元素得到。i>0时, f [ i ] [ j ] f[i][j] f[i][j] = f [ i + 1 ] [ j − 1 ] + f [ i − 1 ] [ j ] f[i+1][j-1]+f[i-1][j] f[i+1][j1]+f[i1][j],该状态可以由某一状态pop一个元素或者某一状态push一个元素得到。

实现

int f[20][20];
int n;
int main()
{
    memset(f,0,sizeof(f));
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
       f[i][0]=1;
    for(int j=1;j<=n;j++)
       for(int i=0;i<=n;i++)
       //我们要推f[0][n],所以i要从零开始跑
        {
          if(i>=1) 
            f[i][j]=f[i-1][j]+f[i+1][j-1];
          if(i==0)//栈内没有东西
            f[i][j]=f[i+1][j-1];
        }
    printf("%d",f[0][n]);
    return 0;
}

P1028 [NOIP2001 普及组] 数的计算

思路

一个简单的dp~ 注意dp[i]++

实现

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[1010];
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int cur = 1;cur<=i/2;cur++)
		{
			dp[i] +=dp[cur];
		}
		dp[i]++; //记得加上自身
	}
	cout<<dp[n];
    return 0;
}

P1928 外星密码

思路

参考了非常好的题解~注意oj里应该是ctrl z结束而不是换行符

实现

string read()
{
	int n;
	string s="",s1;
	char c;
	while (cin>>c)//一直读入字符,直到Ctrl+z  //cin会忽略换行符 所以这里写!='\n'之类的没有意义
	{
		if (c=='[')
		{
			cin>>n;//读入D
			s1=read();//读入X
			while (n--) s+=s1;//重复D次X
            //注:上面不能写成while (n--) s+=read();
		}
		else 
		{
			if (c==']') return s;//返回X
		    else s+=c;//如果不是'['和']',那就是X的一个字符,所以加进X
		}
	}
}
int main()
{
	cout<<read(); 
	return 0;
}

P1164 小A点菜

思路

明确dp数组的定义: f [ i ] [ j ] f[i][j] f[i][j]表示前i道菜花了j元,f记录当前状态下有几种情况。
状态转移有三种情况,剩的钱不够买这道菜,那就只能不买(废话) f [ i ] [ j ] f[i][j] f[i][j] = f [ i − 1 ] [ j ] f[i-1][j] f[i1][j]。剩的钱刚好够买这道菜,那就要么不买,要么买这道菜然后结束。剩的钱比这道菜的价格多,那就要么不买要么买。(废话)

实现

#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
using namespace std;
int main(){
	int n,m;

	cin>>n>>m;
	vector<int> a(n+1);
	vector<vector<int> > f(n+1,vector<int>(m+1,0)); 
	for(int i=1;i<=n;i++)
	cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(j==a[i]) f[i][j] = f[i-1][j]+1;
			else if(j<a[i]) f[i][j] = f[i-1][j];
			else if(j>a[i]) f[i][j] = f[i-1][j]+f[i-1][j-a[i]];
		}
	}
	cout<<f[n][m];
    return 0;
}

P1990 覆盖墙壁

思路

待补充-

实现

#include<iostream>
using namespace std;

const int maxn=1000002;
const int mod=10000;

int f[maxn],g[maxn];

int main()
{
	int n;
	cin>>n;
	f[0]=1;	//g[0]=0
	f[1]=g[1]=1;
	for(int i=2;i<=n;i++)
	{
		f[i]=((f[i-1]+f[i-2])%mod+2*g[i-2]%mod)%mod;
		g[i]=(g[i-1]+f[i-1])%mod;
	}
	cout<<f[n];
	return 0;
}

欢迎指正-

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值