Codeforces1455F.String and Operations 字符串dp

Codeforces1455F.String and Operations

题意

给定一个长度为\(n\)的字符串\(s\),字符集大小为\(k\),有\(n\)次操作,第\(i\)次操作会对原本在\(s\)中第\(i\)位的字符做如下四种之一的操作:

  • \(L\) ,和字符串中前一位字符交换。
  • \(R\),和字符串中后一位字符交换。
  • \(D\),将该字符变为字符集中的下一位字符。
  • \(U\),将该字符变为字符集中的上一位字符。
  • \(0\),什么都不做。

分析

通过分析可以得出,原本在第\(i\)位的字符最多可以向左移动到第\(i-2\)位,通过在第\(i-1,i-2\)位字符连续做\(RL\)操作。

\(s[i-2]s[i-1]s[i]->s[i-2]s[i]s[i-1]->s[i]s[i-2]s[i-1]\)

\(dp[i]\)为操作前\(i\)位得到的字典序最小的字符串。

\(dp[i]\)通过对第\(i+1\)位字符做\(D~or~U~or~L~or~0\)操作,转移到\(dp[i+1]\)

\(dp[i]\)通过对第\(i+1,i+2\)位字符连续做\(RD~or~RU~or~R0~or~RL\)操作,转移到\(dp[i+2]\)

Code

#include<bits/stdc++.h>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e5+10;
const int inf=1e9;
int t,n,k;
char s[510];
string dp[510];
int main(){
    ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    cin>>t;
    while(t--){
        cin>>n>>k;
        cin>>s+1;
        rep(i,0,n) dp[i].clear();
        rep(i,1,n) dp[i].pb('~');
        rep(i,0,n-1){
            char c=s[i+1];
            c=min({c,char((s[i+1]-'a'+k-1)%k+'a'),char((s[i+1]-'a'+1)%k+'a')});
            dp[i+1]=min(dp[i+1],dp[i]+c);//D or U
            dp[i+1]=min(dp[i+1],dp[i].substr(0,i-1)+s[i+1]+dp[i].back()); //L
            if(i==0) continue;
            dp[i+1]=min(dp[i+1],dp[i-1]+c+s[i]); //RD or RU or R0
            dp[i+2]=min(dp[i+2],dp[i].substr(0,i-1)+s[i+2]+dp[i].back()+s[i+1]);//RL
        }
        cout<<dp[n]<<endl;
    }
    return 0;
}
posted @ 2020-12-02 21:37  xyq0220  阅读(95)  评论(0编辑  收藏  举报