题目:长度为m的字符串插入n个加号求最小和。例如string str="123456",n=2;输出12+34+56的和为102,同时输出2 4,也就是加号位置。下面为实现思路:
实现过程主要就是区间dp的思想,其中状态转移方程为dp[i][j] = min(dp[k][j - 1] + getnum(str.substr(k, i-k)), dp[i][j]);//其中dp[i][j]表示1-i中使用了j个加号,在这里我用struct主要就是记录加号的位置。
#include<iostream> #include<ctime> #include<vector> #include<string> #include<algorithm> #include<sstream> using namespace std; //把字符串转化成对应的整数例如字符串"123"的getnum值就是123 int getnum(string str) { if (str.size() <= 0)return 0; int sum = 0; for (int i = 0; i < str.size(); i++) { sum = 10 * sum + (str[i] - '0'); } return sum; } //把字符串中每个数字分别相加例如"123"的getnum1就是6 int getnum1(string str) { int sum = 0; for (int i = 0; i < str.size(); i++) { sum = sum + (str[i] - '0'); } return sum; } struct node { int value; int k; }; int main() { string str = "1234567891"; int n = 3; int m = str.size(); vector<vector<node>>dp(m + 1, vector<node>(n+1)); for (int i = 0; i < m+1; i++) { for (int j = 0; j < n+1; j++) { dp[i][j].value = 9999999; dp[i][j].k = 0; } } vector<int>recordpos;//记录加号的位置 dp[0][0].value = 0; int index = 0; for (int i = 0; i <=m; i++) { dp[i][0].value = getnum(str.substr(0,i)); } for (int j = 0; j <=n; j++) { dp[0][j].value = 0; } for (int i = 1; i < m+1; i++) { for (int j =1; j< n+1; j++) { if (j >= i - 1)dp[i][j].value = getnum1(str.substr(0, i)); else { for (int k = 1; k <=i; k++) { //dp[i][j] = min(dp[k][j - 1] + getnum(str.substr(k, i-k)), dp[i][j]);//其中dp[i][j]表示1-i中使用了j个加号 if (dp[i][j].value>dp[k][j - 1].value + getnum(str.substr(k, i - k))) { dp[i][j].value = dp[k][j - 1].value + getnum(str.substr(k, i - k)); //if (i==m)recordpos.push_back(k); dp[i][j].k = k; } } } } } cout << dp[m][n].value << endl; cout << dp[m][n].k << endl; cout << dp[4][1].k << endl; int k = dp[m][n].k; int y = n; while (k>0 && n>0) { recordpos.push_back(k); y--; m = k; k = dp[m][y].k; } for (int i = 0; i < recordpos.size(); i++) { cout << recordpos[i] << " "; } cout << endl; cin.get(); return 0; }