标签:
题目链接:点击打开链接
题意:
给定2*n长的数字。
把这个数字拆成2个长度为n的数字,且相对位置不变。使得拆后得到的2个数字的和最大。
输出一个方案。
显然是中途相遇法,先计算左半段,再计算右半段
分别状压左半段和右半段,注意左半段状压后要在末尾补上0。
代码估计哪里有小越界==,数组开大了一点才过。。具体就不查了。
#include<iostream> #include<stdio.h> #include<string.h> #include<string> #include<queue> #include<math.h> template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if (x>9) pt(x / 10); putchar(x % 10 + '0'); } using namespace std; typedef long long ll; const int N = 18; string s; int n; int a[N << 1], siz[1 << N]; ll ten[N + 10]; ll dp[2][1 << N], d[2][1 << N], sum[2][N+10], status[2][N+10]; void go(int cur, int off){ dp[cur][0] = 0; for (int i = 1; i < (1 << n); i++) for (int j = 0; j < n; j++) if ((i&(1 << j))>0){ dp[cur][i] = dp[cur][i ^ (1 << j)] * 10 + a[n-1-j + off]; break; } d[cur][(1 << n) - 1] = 0; for (int i = (1 << n) - 2; i >= 0; i--) for (int j = 0; j < n; j++) if ((i&(1 << j)) == 0){ d[cur][i] = d[cur][i ^ (1 << j)] * 10 + a[n-1-j + off]; break; } if (cur == 0){ for (int i = 0; i < (1 << n); i++){ dp[cur][i] *= ten[n - siz[i]]; d[cur][i] *= ten[siz[i]]; } } for (int i = 0; i <= n; i++)sum[cur][i] = -1; for (int i = 0; i < (1 << n); i++) if (dp[cur][i] + d[cur][i] > sum[cur][siz[i]]) { sum[cur][siz[i]] = dp[cur][i] + d[cur][i]; status[cur][siz[i]] = i; } } void put(ll x){ for (int i = n - 1; i >= 0; i--) if (x&(1LL << i))putchar('M'); else putchar('H'); } int main(){ ten[0] = 1; for (int i = 1; i < N; i++)ten[i] = ten[i - 1] * 10; rd(n); cin >> s; for (int i = 0; i < (1 << n); i++){ int j = i; siz[i] = 0; while (j>0){ siz[i]++; j &= j - 1; } } for (int i = 0; i < s.length(); i++)a[i] = s[i] - '0'; go(0, 0); go(1, n); ll ans = -1; pair<ll, ll> p; for (int i = 0; i <= n; i++) if(ans<sum[0][i] + sum[1][n - i]) { ans = sum[0][i] + sum[1][n - i]; p = pair<ll,ll>(status[0][i], status[1][ n - i ]); } put(p.first); put(p.second); puts(""); return 0; }
Codeforces 31E TV Game 中途相遇法 状压dp
标签:
原文地址:http://blog.csdn.net/qq574857122/article/details/44516993