[题解]AT_abc225_f [ABC225F] String Cards

思路

Part 1 弱化版#

看到这道题的第一眼想到了 P1012 这道题。

但是,这两道题选择的数量是有区别的。

我们可以由拼数得出一个结论性的排序规则(这里就不多做解释了):

inline bool cmp(string a,string b){  
    return a + b < b + a;  
}  

如果用这样的做法,有 hack

Part 2 状态定义#

我们首先可以定义状态 dpi,j 为在前 i 个字符串中取 j 个字符串字典序最小的结果。

我们便能很轻松的得出以下状态转移方程:

dpi,j=min(dpi1,j,dpi1,j1+si)

但是,仔细一看就能发现一些问题:在你搞字典序最小的字符串时,是不是先确定前面的字符串再确定后面的字符串吗?计算机也是这样的。

所以,我们修改状态函数 dpi,j 表示在后 i 个字符串中取 j 个字符串字典序最小的结果。

状态转移方程为:

dpi,j=min(dpi+1,j,si+dpi+1,j1)

Part 3 整理#

我们由拼数这道题可以再次得出一个结论:如果假设按照上述排序规则排序后,要使自字典序最小的字符串序列为 sa1,sa2,,sak,那么 a 序列必定是严格单调递增的。

那么,这题何尝不是呢?

所以,我们要在执行 DP 前,按照上述排序规则排一次序。时间复杂度为:Θ(nlogn+nk)

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 60;  
int n,k;  
string s[N];  
string dp[N][N];  
  
inline bool cmp(string a,string b){  
    return a + b < b + a;  
}  
  
int main(){  
    ios::sync_with_stdio(0);  
    cin.tie(0);  
    cout.tie(0);  
    cin >> n >> k;  
    for (re int i = 1;i <= n;i++) cin >> s[i];  
    sort(s + 1,s + 1 + n,cmp);//排序   
    for (re int i = 1;i <= n;i++){//将 dp 数组初始化为正无穷   
        for (re int j = 1;j <= k;j++) dp[i][j] = "{";//因为 '{' 的 ASCII 码比 'x' 的大   
    }  
    dp[n][1] = s[n];//状态起点   
    for (re int i = n - 1;i;i--){//转移   
        for (re int j = 1;j <= k;j++) dp[i][j] = min(dp[i + 1][j],s[i] + dp[i + 1][j - 1]);  
    }  
    cout << dp[1][k];  
    return 0;  
}  

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18261955

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示