[题解]AT_abc225_f [ABC225F] String Cards
思路
Part 1 弱化版#
看到这道题的第一眼想到了 P1012 这道题。
但是,这两道题选择的数量是有区别的。
我们可以由拼数得出一个结论性的排序规则(这里就不多做解释了):
inline bool cmp(string a,string b){
return a + b < b + a;
}
如果用这样的做法,有 hack。
Part 2 状态定义#
我们首先可以定义状态 为在前 个字符串中取 个字符串字典序最小的结果。
我们便能很轻松的得出以下状态转移方程:
但是,仔细一看就能发现一些问题:在你搞字典序最小的字符串时,是不是先确定前面的字符串再确定后面的字符串吗?计算机也是这样的。
所以,我们修改状态函数 表示在后 个字符串中取 个字符串字典序最小的结果。
状态转移方程为:
Part 3 整理#
我们由拼数这道题可以再次得出一个结论:如果假设按照上述排序规则排序后,要使自字典序最小的字符串序列为 ,那么 序列必定是严格单调递增的。
那么,这题何尝不是呢?
所以,我们要在执行 DP 前,按照上述排序规则排一次序。时间复杂度为:。
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 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】