link
我們應該可以想到乙個這樣的轉移方程:
\(dp[i]=\min \limits^_(dp[i],dp[j]+|sum[i]-sum[j]-l-1|^p)\),
其中\(dp[i]\)表示排版完前\(i\)句的最小不協調度,記\(sum[i]=\sum\limits^_+i\)(預設每句後有空格),我們就能得到這個\(o(n^2)\)的轉移方程然而顯然過不了.
那怎麼辦呢?
當\(p=2\)時,顯然我們可以使用斜率優化來解決這道題,但是......因此,我們需要尋找一種適用範圍在這道題更為廣闊的方法.
通過嚴謹的猜想與證明打表,我們可以發現,對於\(j,\(dp[i]\)的最優決策點總是比\(dp[j]\)要大,這說明什麼?最優決策點單調遞增.
我們可以把乙個決策點\(p\)的轉移函式畫出來,設其為\(f_(i)\),我們知道,又因為\(f_p'(i)=p|sum[i]-sum[j]-l-1|^\)單調遞增,那麼對於兩個決策函式\(f_,f_\)只會有乙個交點,在這個交點之後,\(f_\)就再也追不上\(f_\)了.
那麼,對於每乙個決策點\(p\),它只會是一段連續區間的最優決策點,我們可以記錄乙個三元組\(\)表示在\(l\)到\(r\)這段區間裡,最優決策點是\(pos\).我們可以用乙個單調佇列維護這個東西.
具體的,對於新加入乙個位置,我們二分出上乙個決策點的轉移函式和當前位置轉移函式的交點,那就可以更新上乙個決策點區間的右端點和這乙個新加入的決策點區間的左端點.若某決策點的右端點已經小於當前位置,直接從佇列裡彈出.若某決策點其決策函式在其左端點處的函式值比當前位置的決策函式在同一位置時的函式值大,那麼那個決策點也沒有存在的必要了.
注意\(dp\)值域過大,要開long double換取更大的值域.
#include #define ld long double
using namespace std;
int t,n,l,p,l,r;
char s[100005][35];
ld dp[100005],sum[100005];
int ans[100005],pre[100005];
struct queueq[100005];
inline int read()
while(ch>='0'&&ch<='9')
return x*f;
}inline ld quick_power(ld x,int k)
return res;
}inline ld get(int i,int j)
return res;
}int main()
q[l=r=1]=(queue);
for(register int i=1;i<=n;++i);}}
if(dp[n]>1e18)
printf("too hard to arrange\n");
else
ans[cnt+1]=0;
for(register int i=cnt;i;--i)
putchar('\n');}}
printf("--------------------\n");
}return 0;
}
決策單調性的動態規劃 noi2009詩人小G
關於決策單調性在網上有一篇非常好的 1d1d動態規劃優化初步 那麼我們的任務就是證明決策單調性在直接套用模板即可,所謂決策單調性,就是我們要證明這樣乙個命題 如果 f k 的最優決策是j,f k 1 的最優決策是i,ik 使用j轉移都會比使用i轉移優,對於所有f l l k 使用i轉移都會比使用j轉...
noi2009變換序列
2009年noi全國競賽 時間限制 1 s 空間限制 128000 kb 題目等級 大師 master 題解 description 對於n個整數0,1,n 1,乙個變換序列t可以將i變成ti,其中 ti 且ui 1 to n 1 任意x,y 定義x和y之間的距離d x,y min。給定每個i和ti...
NOI2009 變換序列
讀懂題意後發現這道題最主要是要求出字典序最小的排列,考察了匈牙利演算法的實質。首先對於 d i 的定義,我們可以解出可能的 t i 然後將 i 與 t i 連邊,求最大匹配。如果最大匹配 但是要求字典序最小。第一中方法在我 ac 後翻看題解而寫的。這個程式是根據匈牙利演算法的實質寫的。對於乙個待匹配...