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;
}
原文地址:https://www.cnblogs.com/xyq0220/p/14076650.html