wustoj 1269: 劃分數 (搜尋、dp兩種解法)
阿新 • • 發佈:2019-02-15
思路1:
搜尋,n分成m份,可以看成在中間切m-1次,往下搜,最後一次時統計結果就夠了。
ps:這種方法如果n、m 的範圍大一點是要TLE的,所以還是要用dp解決。
程式碼:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<cmath> #include<set> #include<stack> #include<algorithm> #define maxn 1005 #define MAXN 1000005 #define eps 1e-6 #define INF 0x3f3f3f3f using namespace std; int n,m,ans; void dfs(int le,int cut,int pre) // 當前的左邊位置 還要切幾次 上一次的長度 { int i,j; if(cut==1) // 還需要切一次的時候統計 { ans+=max(0,(n-le+1)/2-pre+1); return ; } for(i=pre;le-1+(cut+1)*i<=n;i++) // 切一次等於改變左邊的位置 { dfs(le+i,cut-1,i); } } int main() { int i,j,t; while(~scanf("%d%d",&n,&m)) { ans=0; dfs(1,m-1,1); printf("%d\n",ans); } return 0; }
思路2:
dp,dp[i][j]表示 i 分成 j 份時的方法總數。
自己dp太弱了,方程有點難想的。
方程:
dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
意義:dp[i][j] 的第一份有兩種情況,
1.第一份為1,那麼將這份去掉份數少了1(j少了1),i 同時也少了1,所以這種情況由dp[i-1][j-1]推得。
2.第一份大於1,那麼後面的每份都大於1 ,將每份都減去1,則i變為 i-j ,j 不變,所以這種情況由 dp[i-j][j]推得。
程式碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define maxn 15 #define eps 1e-10 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,m,ans; int dp[205][10]; int main() { int i,j; memset(dp,0,sizeof(dp)); for(i=1;i<=200;i++) { dp[i][1]=1; } for(i=1;i<=200;i++) { for(j=2;j<=i&&j<=6;j++) { dp[i][j]=dp[i-1][j-1]+dp[i-j][j]; } } while(~scanf("%d%d",&n,&m)) { printf("%d\n",dp[n][m]); } return 0; }