传送门

Description

给你一个长度为\(2n\)的数字,每次可以从左侧选一个数字,加入连接到一个数字\(A\)或另一个数字\(B\)后面。\(A,B\)初始为\(0\)。\(A\)与\(B\)必须恰好被连接\(n\)次。最大化\(A,B\)的和,输出方案

Input

第一行是\(n\),第二行是长度为\(2n\)的数字

Output

从左到右输出该数字第几位被如何处理。连接到\(A\)输出\(H\),连接到\(B\)输出\(M\)。

Hint

\(1~\leq~n~\leq~18\)

Solution

看起来像是个DP啊……

考虑如果正向DP的话,每次选择一个数,数字和增加多少依赖于之前那个数字选了多少。这显然是有后效性的,难以处理。

考虑反过来DP。

这样每次选一个数只依赖于之前选了多少位,可以直接设到状态里面。于是可以设\(f_{i,j}\)为\(A\)选了\(i\)位,\(B\)选了\(j\)位的数字和,转移显然。

Code

#include<cstdio>
#define rg register
#define ci const int
#define cl const long long typedef long long int ll; template <typename T>
inline void qr(T &x) {
rg char ch=getchar(),lst=' ';
while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst == '-') x=-x;
} namespace IO {
char buf[120];
} template <typename T>
inline void qw(T x,const char aft,const bool pt) {
if(x < 0) {x=-x,putchar('-');}
rg int top=0;
do {IO::buf[++top]=x%10+'0';} while(x/=10);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
} template <typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template <typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template <typename T>
inline T mabs(const T a) {return a < 0 ? -a : a;} template <typename T>
inline void mswap(T &_a,T &_b) {
T _temp=_a;_a=_b;_b=_temp;
} const int maxn = 40;
const int INF = 0x3f3f3f3f; int n,dn;
int MU[maxn];
ll frog[maxn][maxn],ten[maxn]={1};
char s[maxn];
bool pre[maxn][maxn]; void dfs(ci,ci); int main() {
qr(n);
scanf("%s",s+1);
dn=n<<1;
for(rg int i=dn;i;--i) MU[dn-i+1]=s[i]-'0';
for(rg int i=1;i<n;++i) ten[i]=ten[i-1]*10ll;
for(rg int i=0;i<maxn;++i) for(rg int j=0;j<maxn;++j) frog[i][j]=-INF;
frog[0][0]=0;
for(rg int i=0;i<=n;++i) {
for(rg int j=0;j<=n;++j) {
int len=i+j;
if(i) frog[i][j]=frog[i-1][j]+MU[len]*ten[i-1];
if(j) {
if(frog[i][j] < frog[i][j-1]+MU[len]*ten[j-1]) {
frog[i][j]=frog[i][j-1]+MU[len]*ten[j-1];pre[i][j]=true;
}
}
}
}
dfs(n,n);
putchar('\n');
return 0;
} void dfs(ci x,ci y) {
if((!x) && (!y)) return;
if(pre[x][y]) {putchar('H');dfs(x,y-1);}
else {putchar('M');dfs(x-1,y);}
}

Summary

在序列上的线性DP,当正向难以转移时,可以考虑反向DP。

最新文章

  1. fool
  2. 在docker里面安装部署应用
  3. /etc/passwd /etc/shadow
  4. 使用Npoi向Excel中插入图片
  5. Codeforces Round #361 (Div. 2)
  6. Transformation
  7. osg for android (一) 简单几何物体的加载与显示
  8. discuz!迁移指南
  9. vim如何显示行号
  10. VCS使用学习笔记(1)——Verilog相关的仿真知识
  11. python-函数参数
  12. Vue Router学习笔记
  13. c++与java的几个不同点
  14. python:利用smtplib模块发送邮件
  15. Mac操作的一些技能
  16. Redis notes
  17. 通过Navicat Premium迁移Oracle到EDB迁移实战
  18. (LeetCode 53)Maximum Subarray
  19. ApplicationContext的三个常用实现类:
  20. maven编译报错 -source 1.5 中不支持 lambda(或diamond) 表达式,编码 UTF-8 的不可映射字符

热门文章

  1. 自动化运维工具saltstack01 -- 之SaltStack介绍、安装与基础使用
  2. PostgreSQL9.6主从配置
  3. PKI(Public Key Infrastucture)介绍
  4. mysql基础知识大全
  5. Scrum立会报告+燃尽图(十一月二十三日总第三十一次):界面修改及新页面添加
  6. 马士兵老师hadoop讲解总结博客地址记录(啊啊啊啊啊,自己没有保存写好的博客...)
  7. 【Nginx】转:Nginx try_files
  8. pixi.js tools
  9. 【.Net】win10 uwp unix timestamp 时间戳 转 DateTime
  10. EM算法[转]