The meaning of problems
There are post offices p, n villages, post offices can only be built in the village,
Seeking to send a letter so that all distance and minimum values. ,
SOLUTION:
First of dp can n3
dp i, j represent the i-th place before the establishment of minimum cost j a post office,
In the process at an arbitrary interval to establish a post office is a minimum cost (an interval put a post office, then placed in a median position most)
Thinking about how to optimize dp
eliminate the one-dimensional binary wqs
Set f (x) = g (x) + kx, each set up a post office should increase the value of k, look at the current f (x) is taken to the maximum and the relationship between x and p of questions asked
CODE:
#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]; int c[maxn]; int dp[maxn]; inline int check(int mid) { for(int i=1;i<=n;i++) dp[i]=1e16; dp[0]=0; for(int i=1;i<=n;i++) { for(int j=1;j<=i;j++) { if(dp[i]>dp[j-1] + dis[j][i] + mid) { dp[i]=dp[j-1] + dis[j][i] + mid; c[i]=c[j-1]+1; } } } //for(int i=1;i<=n;i++)cout<<dp[i]<<" ";cout<<endl; return c[n]; } void work() { int l=-1e9,r=1e9;int ans=0; while(l<=r) { int mid=l+r>>1; if(check(mid)<=p)ans=mid,r=mid-1; else l=mid+1; // cout<<mid<<" "<<check(mid)<<endl; } check(ans); long long t = dp[n] - p*ans; cout<<t<<endl; } 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; // coordinate origin of the drawing can move to prove a [mid] each prefix and adding Finally understood as a [mid] @ SUM [J] -sum [MID] to [mid + 1, j] summing, sum [mid-1] -sum [i-1] to [i, mid-1] summation dis [i] [j] = (sum [j] -sum [mid]) - (j -mid) * A [MID] + (MID-I) * A [MID] - (SUM [-MID. 1] -sum [-I. 1]); } } Work (); } return 0; }