日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJXXXX: [IOI2000]邮局——四边形不等式优化初探

發布時間:2024/4/15 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJXXXX: [IOI2000]邮局——四边形不等式优化初探 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

貌似$BZOJ$上并沒有這個題。。。

是嫌這個題水了么。。。

還是要氪金權限號???

這里附上洛谷的題面:洛谷P4767 [IOI2000]郵局

題目描述

高速公路旁邊有一些村莊。高速公路表示為整數軸,每個村莊的位置用單個整數坐標標識。沒有兩個在同樣地方的村莊。兩個位置之間的距離是其整數坐標差的絕對值。

郵局將建在一些,但不一定是所有的村莊中。為了建立郵局,應選擇他們建造的位置,使每個村莊與其最近的郵局之間的距離總和最小。

你要編寫一個程序,已知村莊的位置和郵局的數量,計算每個村莊和最近的郵局之間所有距離的最小可能的總和。

輸入輸出格式

輸入格式:

?

第一行包含兩個整數:第一個是村莊$V$的數量,第二個是郵局的數量$P$,$1 \leq P \leq 300$,$P \leq V \leq 3000$.

第二行包含$V$個整數。這些整數是村莊的位置。對于每個位置$X$,認為$1 \leq X \leq 10000$

?

輸出格式:

?

第一行包含一個整數$S$,它是每個村莊與其最近的郵局之間的所有距離的總和。

?

輸入輸出樣例

輸入樣例#1:?復制 10 5 1 2 3 6 7 9 11 22 44 50 輸出樣例#1:?復制 9

說明

對于40%的數據,$V \leq 300$


題解Here!

首先這是個區間$DP$對吧。

我們一步一步來分析:

首先要將村莊位置排個序,不用多說。

下面開始$DP$。

$No. 1:\text{普通DP}$:

設$dp[i][j]$表示前$i$個村莊中建了$j$個郵局的最優方案。

轉移方程長這個樣:

$$dp[i][j]=\max\{\ dp[k][j-1]+dis(k+1,i)\ |\ k\in[0,i)\}$$

其中$dis(l,r)$表示在$[l,r]$這個區間內的村莊中建一個郵局對答案的貢獻。

利用人類智慧可知把郵局建在中間花費最少。。。

復雜度上限是$O(n^3m)$,實測可以$40\text{分}$。

代碼如下:

inline int abs(int x){return x>0?x:-x;} inline int dis(int l,int r){int mid=(l+r)>>1,s=0;for(int i=l;i<=r;i++)s+=abs(pos[i]-pos[mid]);//pos是村莊位置return s; } void work(){dp[0][0]=0;for(int i=1;i<=n;i++)for(int j=1;j<=m&&j<=i;j++)for(int k=0;k<i;k++)dp[i][j]=min(dp[i][j],dp[k][j-1]+dis(k+1,i));printf("%d\n",dp[n][m]); }

$No. 2:\text{普通DP+優化}$:

我們發現我們的求貢獻還要$O(n)$的復雜度,考慮對其進行優化。

我們知道:

$$dis(l,r)=\sum_{i=l}^r|pos_i-pos_{mid}|,mid=\frac{l+r}{2}$$

因為我們的$pos$是有序的,于是:

$$dis(l,r)=\sum_{i=l}^{mid-1}(pos_{mid}-pos_i)+\sum_{i=mid+1}^r(pos_i-pos_{mid}),mid=\frac{l+r}{2}$$

顯然拆開:

$$dis(l,r)=(mid-l)pos_{mid}-\sum_{i=l}^{mid-1}pos_i+\sum_{i=mid+1}^rpos_i-(r-mid)pos_{mid},mid=\frac{l+r}{2}$$

合并:

$$dis(l,r)=(2mid-l-r)pos_{mid}+\sum_{i=mid+1}^rpos_i-\sum_{i=l}^{mid-1}pos_i,mid=\frac{l+r}{2}$$

注意,這個地方$2mid-l-r \neq 0$,因為實際算$mid$時,算的其實是$\lfloor\frac{l+r}{2}\rfloor$。

但是這個并不影響復雜度,所以可以保留。

關鍵是后面那兩個$\sum$怎么整?

前綴和!

設$sum(x)=\sum_{i=1}^xpos_i$,則:

$$\left.\begin{array}{}dis(l,r)&=&(2mid-l-r)pos_{mid}+(sum(r)-sum(mid))-(sum(mid-1)-sum(l-1))\\&=&(2mid-l-r)pos_{mid}+sum(l-1)+sum(r)-sum(mid)-sum(mid-1)\end{array}\right.$$

于是預處理前綴和,就可以$O(1)$計算$dis(l,r)$了!

復雜度$O(n^2m)$,實測$60\text{分}$。

代碼如下:

inline int dis(int l,int r){int mid=(l+r)>>1;return ((sum[r]-sum[mid])-(sum[mid-1]-sum[l-1])+(mid*2-l-r)*pos[mid]); } void work(){dp[0][0]=0;for(int i=1;i<=n;i++)for(int j=1;j<=m&&j<=i;j++)for(int k=0;k<i;k++)dp[i][j]=min(dp[i][j],dp[k][j-1]+dis(k+1,i));printf("%d\n",dp[n][m]); }

$No. 3:\text{DP+四邊形不等式}$:

四邊形不等式優化就是:

在$DP$過程中滿足:

$$dp[a][c]+dp[b][d]<=dp[a][d]+dp[b][c]$$

并且決策具有單調性。

對于這題,我們發現,$dp[i][j]$的決策只能從$dp[i][j-1],dp[i+1][j]$中選一個進行轉移。

于是就可以用四邊形不等式優化了!

到此,我們證明了這個題其實是個板子題。。。

記得要倒序$DP$。

附代碼:

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define MAXN 3010 using namespace std; int n,m; int pos[MAXN],sum[MAXN],from[MAXN][MAXN],dp[MAXN][MAXN]; inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w; } inline int dis(int l,int r){int mid=(l+r)>>1;return ((sum[r]-sum[mid])-(sum[mid-1]-sum[l-1])+(mid*2-l-r)*pos[mid]); } void work(){for(int j=2;j<=m;j++){from[n+1][j]=n;for(int i=n;i>=1;i--){for(int k=from[i][j-1];k<=from[i+1][j];k++){if(dp[k][j-1]+dis(k+1,i)<dp[i][j]){dp[i][j]=dp[k][j-1]+dis(k+1,i);from[i][j]=k;}}}}printf("%d\n",dp[n][m]); } void init(){n=read();m=read();memset(dp,127,sizeof(dp));for(int i=1;i<=n;i++)pos[i]=read();sort(pos+1,pos+n+1);sum[0]=0;for(int i=1;i<=n;i++){sum[i]=sum[i-1]+pos[i];dp[i][1]=dis(1,i);} } int main(){init();work();return 0; }

?

轉載于:https://www.cnblogs.com/Yangrui-Blog/p/9862813.html

總結

以上是生活随笔為你收集整理的BZOJXXXX: [IOI2000]邮局——四边形不等式优化初探的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。