1. 程式人生 > 其它 >Part 1.4 函式,遞迴及遞推

Part 1.4 函式,遞迴及遞推

補一補基礎題

P1028 [NOIP2001 普及組] 數的計算

題目描述

我們要求找出具有下列性質數的個數(包含輸入的正整數 nnn)。

先輸入一個正整數 nnn(n≤1000n \le 1000n≤1000),然後對此正整數按照如下方法進行處理:

不作任何處理;

在它的左邊加上一個正整數,但該正整數不能超過原數的一半;

加上數後,繼續按此規則進行處理,直到不能再加正整數為止。

輸入格式

111 個正整數 nnn(n≤1000n \le 1000n≤1000)
輸出格式

111 個整數,表示具有該性質數的個數。
輸入輸出樣例
輸入

6

輸出

6

#include<iostream>
using namespace
std; int main() { int n,cnt=1,f[1000]; f[0]=f[1]=1; cin>>n; for(int i=2;i<=n;i++) { if(i%2==0) { f[i]=f[i-1]+f[i/2]; } else f[i]=f[i-1]; } cout<<f[n]<<endl; }

感覺學了這個對動態規劃會有更深層次的瞭解,哎,基礎很重要呀,感覺要把基礎打牢固了,其實一些比賽就是比誰做的更快,掌握的更牢固呀。

P1464 Function

#include <cstdio>
#define LL long long

LL dp[25][25][25];

LL w(LL a, LL b, LL c)
{
    if(a <= 0 || b <= 0 || c <= 0) return 1;//兩個特判,題意裡都有的。
    if(a > 20 || b > 20 || c > 20) return w(20, 20, 20);
    
    if(a <b && b < c)//情況一,每一個沒有儲存過的“w”值全部儲存,如果有就直接呼叫。
{ if(dp[a][b][c-1] == 0) { dp[a][b][c-1] = w(a, b, c-1); } if(dp[a][b-1][c-1] == 0) { dp[a][b-1][c-1] = w(a, b-1 ,c-1); } if(dp[a][b-1][c] == 0) { dp[a][b-1][c] = w(a, b-1, c); } dp[a][b][c] = dp[a][b][c-1] + dp[a][b-1][c-1] - dp[a][b-1][c]; } else//同上 { if(dp[a-1][b][c] == 0) { dp[a-1][b][c] = w(a-1, b, c); } if(dp[a-1][b-1][c] == 0) { dp[a-1][b-1][c] = w(a-1, b-1 ,c); } if(dp[a-1][b][c-1] == 0) { dp[a-1][b][c-1] = w(a-1, b, c-1); } if(dp[a-1][b-1][c-1] == 0) { dp[a-1][b-1][c-1] = w(a-1, b-1, c-1); } dp[a][b][c] = dp[a-1][b][c] + dp[a-1][b][c-1] + dp[a-1][b-1][c] - dp[a-1][b-1][c-1]; } return dp[a][b][c]; } int main() { LL a, b, c; while(scanf("%lld%lld%lld", &a, &b, &c))//無限輸入,直到“-1 -1 -1” { if(a == -1 && b == -1 && c == -1) return 0;//-1 -1 -1就直接結束,不運算了。 printf("w(%lld, %lld, %lld) = ", a, b, c); printf("%lld\n", w(a, b, c)); } }

感覺還需要掌握記憶話搜尋的精髓

P1025 [NOIP2001 提高組] 數的劃分

題目描述

將整數nnn分成kkk份,且每份不能為空,任意兩個方案不相同(不考慮順序)。

例如:n=7n=7n=7,k=3k=3k=3,下面三種分法被認為是相同的。

1,1,51,1,51,1,5;
1,5,11,5,11,5,1;
5,1,15,1,15,1,1.

問有多少種不同的分法。
輸入格式

n,kn,kn,k (6<n≤2006<n \le 2006<n≤200,2≤k≤62 \le k \le 62≤k≤6)
輸出格式

111個整數,即不同的分法。

#include<iostream>
using namespace std;

int n,k;
inline int dfs(int num,int part,int now)//剩餘待分的數 分的機會數 現在要選出的數
{
    if(part==1)return 1;
    int sum=0;
    for(int i=now;i<=num/part;i++)
    {
        sum+=dfs(num-i,part-1,i);
    }
    return sum;
}

int main()
{
    cin>>n>>k;
    cout<<dfs(n,k,1)<<endl;
}

感覺又是一道很好的dfs題 但是這個的動態規劃感覺有點難想 轉移方程不大會寫呢