题目描述

nn张卡片, 每张卡片上有一个字符串sis_i, 现在要求你从中选出kk张卡片, 使得在所有选取方案中, 这 kk 张卡片连起来的字典序是最小的

思路

根据以下规则排序

1
2
3
bool cmp(string a,string b){
return a + b < b + a;
}

排序后

为什么不选前 kk 个?
k=1,s={ba,b}k = 1,s = \{ba,b\} 排序后就会得到 baba 的字典序小于 bb 的错误结果

考虑 f[i]f[i] 表示为以第i个字符串结尾的最小字典序

倒着跑一边01背包(某个字符串选或不选)

为什么不正向跑呢?

模拟一下样例

4 3
bbaba
bba
b
b

The answer for the following case is bbababb, but it outputs bbababbab.

错误答案前缀覆盖了正确答案,在正向dp的过程中无法对长度进行更改

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int n,m;
string s[55];
string f[55];
bool cmp(string a,string b){
return a+b < b+a;
}
signed main()
{
cin>>n>>m;
forr(i,1,n) cin >> s[i];
forr(i,1,54) f[i] = "{";
sort(s+1,s+1+n,cmp);
for(int i = n;i>=1;i--)
for(int j = m;j >=1;j--)
f[j] = min(f[j],s[i]+f[j-1]);
cout << f[m] << endl;
return 0;
}

感性理解这个排序方式,类似于尝试思路

本题的tutorial也列举了很多错误的思考

来告诉我们需要think && try