两个吃奶一个添下面视频_人妻第一页香蕉网_欧美xxxx少妇_妺妺窝人体色www婷婷

本篇主要從計數(shù)DP上結(jié)合實例分析。


一、計數(shù)類DP——整數(shù)劃分

整數(shù)劃分大體上可以分為3類

(1)考慮順序的拆分方案(即1,1,2;和2,1,1 是兩種不同的方案),這種問題一般轉(zhuǎn)化為完全背包即可解決。

(2)不考慮順序的拆分方案,可以劃分出集(也就是可以有對拆分完全沒貢獻(xiàn)的東西存在(0))

(3)不考慮順序的拆分方案,要求劃分出的集合不為空集(不可以拆出0)

主要討論2,3類DP問題


二、空集存在的情況

對于n的m劃分,可以定義dp[m][n]為所求答案, 考慮任意的拆分序列ai,可以分為兩類

1. 所有ai2都大于0,我們可以每個序列都拿出一個1,則拆分序列變?yōu)?img src="/assets/addons/ueditor/php/upload/image/20221115/1668488640496467.png" title="ai3" alt="ai3" width="17" height="20"/>-1,它的求和為n?m,所以他是n ? m的m劃分 ,對答案的貢獻(xiàn)為dp[i][j-i]。

2. 如果存在ai4=0,可以將之化歸到n的m ? 1劃分,對答案的貢獻(xiàn)為dp[i-1][j]。

從而,有:

dp[i][j]=dp[i?1][j]+dp[i][j?1]

當(dāng)劃分的數(shù)量m太大(m>n)后,第一種情況不存在,

dp[i][j]=dp[i?1][j]

代碼

#include <bits/stdc++.h>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define debug(x) cout<<"> "<< x<<endl;
#define endl '\n'
#define lowbit(x) x&-x
//#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N =10 + 200, mod = 1e9 + 7;
int n,m;
ll dp[N][N];// j 的 i劃分
void solve()
{    
    cin >> n >> m;
    // dp[i][j] = dp[i-1][j] + dp[i][j - i] 
    dp[0][0] = 1;
    for(int i=1;i<=m;i++){
        for(int j=0;j<=n;j++){
            if(j - i >= 0){
                dp[i][j] = dp[i][j-i] + dp[i-1][j];
            }else{
                dp[i][j] = dp[i-1][j];
            }
        }
    }
    cout << dp[m][n] << endl;
}
signed main()
{
    ios::sync_with_stdio();cin.tie();cout.tie();

    solve();

    return 0;
}


三、空集不存在的情況

原來的基礎(chǔ)上只要解決了重復(fù)計數(shù)的部分即可,顯然就是不在考慮ai6中存在0的情況,把上面代碼else去掉。

并且注意初始化dp時,初始化為dp[m][0] = 1 ,防止重復(fù)計算

代碼如下:

#include <bits/stdc++.h>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define debug(x) cout<<"> "<< x<<endl;
#define endl '\n'
#define lowbit(x) x&-x
//#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N =10 + 200, mod = 1e9 + 7;
int n,m;
ll dp[N][N];// j 的 i劃分
void solve()
{    
    cin >> n >> m;
    // dp[i][j] = dp[i-1][j] + dp[i][j - i] 
    dp[0][m] = 1;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            if(j - i >= 0){
                dp[i][j] = dp[i][j-i] + dp[i-1][j];
            }
        }
    }
    cout << dp[m][n] << endl;
}
signed main()
{
    ios::sync_with_stdio();cin.tie();cout.tie();

    solve();

    return 0;
}


點贊(0)

C語言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點擊了解:

一點編程也不會寫的:零基礎(chǔ)C語言學(xué)練課程

解決困擾你多年的C語言疑難雜癥特性的C語言進(jìn)階課程

從零到寫出一個爬蟲的Python編程課程

只會語法寫不出代碼?手把手帶你寫100個編程真題的編程百練課程

信息學(xué)奧賽或C++選手的 必學(xué)C++課程

藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競賽課入門課程

手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程

Dotcpp在線編譯      (登錄可減少運行等待時間)