OpenJ_Bailian - 4152 最佳加法表达式 dp
http://bailian.openjudge.cn/practice/4152?lang=en_US
题解 :dp[i][j]代表前i个字符加j个加号可以得到的最小值,于是dp[i+k[j+1]可以由dp[i][j]得到。具体转移方程看代码。
然后数字是50位所以要用高精度类。自己写了一个
坑:高精度的<和+有bug。一开始的更新方法也在乱写
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<iostream> #include<string> #include<vector> #include<algorithm> #include<string.h> using namespace std; const int N = 50 + 5; typedef long long ll; struct BigInterger { static const int BASE = 1e8; static const int WIDTH = 8; vector<int> s; BigInterger(long long num = 0) { *this = num; } BigInterger operator =(long long num) { s.clear(); do { s.push_back(num%BASE); num /= BASE; } while (num > 0);//num==0 return *this; } BigInterger operator =(const string& str) { s.clear(); int x, len = (str.length() - 1) / WIDTH + 1;//len==width for (int i = 0; i < len; i++) { int end = str.length() - i*WIDTH; int start = max(0, end - WIDTH); sscanf(str.substr(start, end - start).c_str(), "%d", &x); s.push_back(x); } return *this; } BigInterger operator +(const BigInterger& b)const { BigInterger c; c.s.clear(); for (int i = 0, g = 0;; i++) { if (g == 0 && i >= max(s.size(), b.s.size()))break; int x = g; if (i < s.size())x += s[i]; if (i < b.s.size()) x += b.s[i]; c.s.push_back(x%BASE); g = x / BASE; } return c; } BigInterger operator +=(const BigInterger& b) { *this = *this + b; return *this; } bool operator<(const BigInterger& b)const { if (s.size() != b.s.size()) return s.size() < b.s.size(); for (int i = s.size() - 1; i >= 0; i--) { if (s[i] != b.s[i]) return s[i] < b.s[i];//Width 个数字一起比 } return false;//== } bool operator>(const BigInterger &b)const { return b < *this; } bool operator<=(const BigInterger &b)const { return !(b < *this); } bool operator>=(const BigInterger &b)const { return !(*this < b); } bool operator!=(const BigInterger &b)const { return b < *this || *this<b; } bool operator==(const BigInterger &b)const { return!(b < *this) && !(*this<b); } }; ostream& operator <<(ostream &out, const BigInterger& x) { out << x.s.back(); for (int i = x.s.size() - 2; i >= 0; i--) { char buf[20]; sprintf(buf, "%08d", x.s[i]); for (int j = 0; j < strlen(buf); j++)cout << buf[j]; } return out; } istream&operator>>(istream &in, BigInterger&x) { string s; if (!(in >> s))return in; x = s; return in; } BigInterger dp[N][N];//前i个数加j个加号的最小值。 int main() { int n; BigInterger s; string s1; string INF; for (int i = 1; i < 55; i++)INF += "1"; while (cin >> n) { cin >> s1; int len = s1.length(); s = s1; //if (n == 0) {cout << s<<endl; continue;} for (int i = 0; i <= len; i++) for (int j = 0; j <= n; j++) dp[i][j] = INF; for (int i = 1; i <= len; i++) for (int j = 0; j <= n; j++) { if (j == 0) { dp[i][j] = s1.substr(0, i); } else if (i < j + 1) dp[i][j] = INF; else { for (int k = j; k <= i - 1; k++) { BigInterger x; x = s1.substr(k, i - k); dp[i][j] = min(dp[i][j], dp[k][j - 1] + x); } } //cout <<i<<j<<' '<< dp[i][j] << endl; } cout << dp[len][n] << endl; } }
成功的路并不拥挤,因为大部分人都在颓(笑)