1. 程式人生 > >poj1160 Post Office(區間dp)

poj1160 Post Office(區間dp)

題意

有p個郵局,n個村莊,郵局只能建在村莊裡,

求令所有寄信距離之和最短的值。

題解

資料比較弱,O(n^3)過了。

dp[i][j]表示前i個村莊需要j個郵局,

其必為某個前k個村莊用j-1個郵局,k+1到i用1個郵局的最小值。

即可實現轉移,對於某段區間建一個的最小值,郵局一定建在中位數即可。

如果有兩個中位數,顯然兩個地點的值是相等的。

從左中位數a轉移到右中位數b,sum-左一半點*dis(a,b)+右一半點*dis(a,b)=sum,沒變

求dis(i,j)時用的字首和,貌似還有一個O(n²)的轉移做法。①

心得

感覺dp的下標略坑,總是搞不明白,

而且dp的預處理也不知道第一行處理為什麼好。

據說有O(n²)的四邊形優化,待補。②

k的內層迴圈據說也可以優化一下,不是0到i-1。③

一題耽誤6-7hGG。

程式碼

#include <iostream>
#include <algorithm> 
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=300+10; 
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int> 
#define si set<int>
#define pii pair<int,int> 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
//dp[i][j]代表前i個村莊 需要j個郵局的最小花費 
//
int n,p,a[maxn],sum[maxn],dis[maxn][maxn],dp[maxn][maxn];
int main()
{ 
   while(~scanf("%d%d",&n,&p))
   {
   rep(i,1,n)sci(a[i]);
   sort(a+1,a+n+1);
   sum[0]=0;
   rep(i,1,n)sum[i]=sum[i-1]+a[i];
   rep(i,1,n)
   {
   	dis[i][i]=0;
   	rep(j,i+1,n)
   	{
   		int mid=(i+j)/2;
   		//畫圖可證明 座標零點挪動為a[mid]的字首和 可理解成每個相加 最後提出a[mid] 
   	    //sum[j]-sum[mid]為[mid+1,j]的求和,sum[mid-1]-sum[i-1]為[i,mid-1]的求和 
   		dis[i][j]=(sum[j]-sum[mid])-(j-mid)*a[mid]+(mid-i)*a[mid]-(sum[mid-1]-sum[i-1]);
   	}
   }
   mem(dp,INF);
   rep(i,1,n)dp[i][1]=dis[1][i];
   rep(j,2,p)
   {
   		per(i,n,1)
		{ 
   		rep(k,1,i-1)
   		{
   			//前k個用j-1個郵局 k+1到i用1個郵局 
   		   dp[i][j]=min(dp[k][j-1]+dis[k+1][i],dp[i][j]);
   		}
   	    }
   	}
   printf("%d\n",dp[n][p]);//前n個用p個郵局	
   }
   return 0;
}