题目大意:
洛谷
解题思路:
设dp[i]为前i个句子产生的最小代价,很容易就能写出转移方程式:
d
p
i
=
m
i
n
{
d
p
j
+
∣
s
i
−
s
j
−
1
−
L
∣
p
}
,
s
i
=
i
+
∑
j
=
1
i
l
e
n
j
,
j
∈
[
0
,
i
−
1
]
dp_i=min\{dp_j+|s_i-s_j-1-L|^p\} ,s_i=i+\sum_{j=1}^{i}len_j,j\in[0,i-1]
d p i = m i n { d p j + ∣ s i − s j − 1 − L ∣ p } , s i = i + ∑ j = 1 i l e n j , j ∈ [ 0 , i − 1 ] 然后暴力打表发现转移具有单调性 ,接下来方法同[POI2011]Lightning Conductor 决策优化
AC代码:
# include <bits/stdc++.h>
# define ft first
# define sd second
# define IOS ios:: sync_with_stdio ( false ) , cin. tie ( 0 ) , cout. tie ( 0 )
# define seteps ( N) fixed << setprecision ( N)
# define endl "\n"
# define cal ( i, j) dp[ j] + qpow ( abs ( sum[ i] - sum[ j] - l) , p)
const int maxn = 1e5 + 10 ;
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair< int , int > pii;
const ll mod = 1e9 + 7 ;
db qpow ( db a, ll b) {
db res = 1 ;
while ( b) {
if ( b & 1 ) res = res * a;
a = a * a;
b >>= 1 ;
}
return res;
}
int _, n, l, p, q[ maxn] , pre[ maxn] ;
string str[ maxn] ;
db k[ maxn] , dp[ maxn] , sum[ maxn] ;
int find ( int x, int y) {
int lc = y, rc = n + 1 , mc, res = n + 1 ;
while ( lc <= rc) {
mc = ( lc + rc) >> 1 ;
if ( cal ( mc, x) >= cal ( mc, y) ) res = mc, rc = mc - 1 ;
else lc = mc + 1 ;
}
return res;
}
void solve ( ) {
for ( int i = 1 , h = 1 , t = 1 ; i <= n; i++ ) {
while ( h < t && k[ h] <= i) h++ ;
dp[ i] = cal ( i, q[ h] ) ; pre[ i] = q[ h] ;
while ( h < t && k[ t - 1 ] >= find ( q[ t] , i) ) -- t;
k[ t] = find ( q[ t] , i) ; q[ ++ t] = i;
}
}
void init ( ) {
memset ( q, 0 , sizeof ( q) ) ;
}
int main ( ) {
cin >> _;
while ( _-- ) {
cin >> n >> l >> p;
l += 1 ;
init ( ) ;
for ( int i = 1 ; i <= n; i++ ) cin >> str[ i] , sum[ i] = sum[ i - 1 ] + str[ i] . size ( ) + 1 ;
solve ( ) ;
if ( dp[ n] > 1e18 ) puts ( "Too hard to arrange" ) ;
else {
cout << seteps ( 0 ) << dp[ n] << endl;
int tmp = n, t = 0 ;
pre[ 0 ] = - 1 ;
while ( tmp != - 1 ) q[ ++ t] = tmp, tmp = pre[ tmp] ;
while ( t) {
for ( int i = q[ t] + 1 ; i <= q[ t - 1 ] ; i++ )
cout << str[ i] << " \n" [ i == q[ t - 1 ] ] ;
t-- ;
}
}
puts ( "--------------------" ) ;
}
}