ABC都水,不写了。
题意:有一串数字序列,H和M两个人,依次从序列的左边取走数字加在自己的数字后面(开始都为空),每一次有一个人去数字,最后保证每个人都取走n个数字。使得两个人的数字之和最大。
分析:如果做dp比较有经验,这道题还是很简单的。我一开始总想用d[i]表示第i个数字有拿与不拿两种状态,同时再开几维记录两个人分别拿的个数,分别的数字大小等(这不是重点)。但写了半天才发现是错的,因为第i个拿与不拿的最大值不能有d[i-1]决定,因此状态无法转移。
正确的解法是开一个二维数组d[i][j],表示H拿了i个数字,M拿了j个数字此时的最大值,它可以由d[i-1][j]和d[i][j-1]转移过来。由于每个人最后都拿n个数字,因此并不是拿一个数字再把已得数字乘10加上这个数字,而是每拿一个数字根据它的位置乘上10的几次方,这才是它的真正大小。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define PI acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=100005;
int n;
char s[100];
LL d[20][20];
char c[20][20];
LL a[20];
void print(int i,int j);
int main()
{
cin>>n>>s;
a[n]=1;
for(int i=n-1;i>=1;i--)
a[i]=a[i+1]*10;
d[0][0]=0;
for(int i=1;i<=n;i++)
{
d[0][i]=d[0][i-1]+(s[i-1]-'0')*a[i];
c[0][i]='M';
}
for(int i=1;i<=n;i++)
{
d[i][0]=d[i-1][0]+(s[i-1]-'0')*a[i];
c[i][0]='H';
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
LL h=d[i-1][j]+(s[i+j-1]-'0')*a[i];
LL m=d[i][j-1]+(s[i+j-1]-'0')*a[j];
if(h>=m)
{
d[i][j]=h;
c[i][j]='H';
}
else
{
d[i][j]=m;
c[i][j]='M';
}
}
}
print(n,n);
return 0;
}
void print(int i,int j)
{
if(i==0&&j==0)
return;
if(c[i][j]=='H')
{
print(i-1,j);
cout<<"H";
}
else
{
print(i,j-1);
cout<<"M";
}
}