Part 1.4 函式,遞迴及遞推
阿新 • • 發佈:2021-01-25
補一補基礎題
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題 但是這個的動態規劃感覺有點難想 轉移方程不大會寫呢