• AT???? [ABC255D] String Cards 题解


    ATcoder

    Description.

    \(n\) 个字符串,选出 \(K\) 个按任意顺序连接。
    求字典序最小的方案。

    \(1\le k\le n\le 50\)

    Solution.

    首先,当 \(K=n\) 的情况是一个经典原题。
    可以直接 sort(s.begin(),s.end(),[](string a,string b){return a+b<b+a;}); 就做完了。
    这个满足偏序也很好证明,可以直接算哈希值。
    这样就有 \(a\times 26^{|B|}+b\le b\times26^{|A|}+a\),有 \(\frac{a}{26^{|A|}-1}\le \frac{b}{26^{|B|}-1}\)
    同时,排完序后,选出来 \(K\) 个肯定会按原序列顺序排序,证明显然。

    然后,\(K\ne n\) 的时候考虑 dp。
    dp 要求的是全局最优决策的部分肯定是局部最优决策。
    从前往右肯定有问题,因为 aaa 局部最优决策是 a,但是后面连一个 b 就要选 aab
    考虑从后往前,往前接一个相同的字符串,后面肯定字典序越小越好。
    所有从后往前 dp 就行了。

    Coding.

    点击查看代码
    //Coded by leapfrog on 2021.10.29 {{{
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    string s[55],dp[55][55];int n,K;
    int main()
    {
    	read(n,K);for(int i=1;i<=n;i++) cin>>s[i];
    	sort(s+1,s+n+1,[](string a,string b){return a+b<b+a;});
    	for(int i=n;i>=1;i--)
    	{
    		dp[i][n-i+1]=s[i]+dp[i+1][n-i];
    		for(int j=1;j<=n-i;j++) dp[i][j]=min(dp[i+1][j],s[i]+dp[i+1][j-1]);
    	}return cout<<dp[1][K]<<endl,0;
    }
    
  • 相关阅读:
    vue-cli快速搭建
    js严格模式下判断数据类型
    js实现本地的图片压缩上传预览
    web端实现图片放大切换显示预览
    swiper.js在隐藏/显示切换时,轮播出现bug的解决办法
    Zepto.js实现fadeIn,fadeOut功能
    ms
    redis 解决秒杀
    单下滑线 事务 锁
    极验
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15490301.html
Copyright © 2020-2023  润新知