NYOJ 整數劃分(四) (區間dp)
阿新 • • 發佈:2019-02-04
題意:給出兩個整數 n , m ,要求在 n 中加入m - 1 個乘號,將n分成m段,求出這m段的最大乘積
思路:區間dp,我們需要先預處理出第i位到第j位可以湊成的數sum[i][j],之後dp[i][j]表示你在第i個數字添加了j個乘號時的最大值,那麼dp[i][j] =max(dp[i][j],dp[k][j-1] * sum[k+1][i])
解釋一下這個dp陣列就是你在第i個數字放第j個乘號的時候,他能從那個狀態轉移過來呢,它可以由第k個數字(k<i)轉移過來,那麼轉移的價值時多大呢,sum[k+1][i],所以dp[i][j] = max(dp[i][j],dp[k][j-i]*sum[k+1][i])
上程式碼把:
#include <bits/stdc++.h> using namespace std; string ch; long long sum[50][50]; long long dp[50][50]; int main() { int t,m; cin>>t; while(t--) { ch.clear(); memset(sum,0,sizeof(sum)); memset(dp,0,sizeof(dp)); cin>>ch>>m; int len = ch.size(); for(int i = 0 ; i < len ; i++) { sum[i][i] = ch[i] - '0'; for(int j = i+1 ; j < len ; j++) { sum[i][j] = sum[i][j-1] * 10 + ch[j] -'0'; } } for(int i = 0 ; i < len ; i ++) { dp[i][0] = sum[0][i]; } for(int i = 0 ; i < len ; i++) { for(int j = 0 ; j < m ;j ++) { for(int k = 0 ; k < i ;k++) { dp[i][j] = max(dp[i][j] , dp[k][j-1] * sum[k+1][i]); } } } long long ans = -1; printf("%lld\n",dp[len-1][m-1]); } }