我不知道优化,我只知道最暴力的方法,O(V^3),居然100ms不到的过了
设DP[i][j][k]表示考虑前i个小镇,放了j个邮局,最后一个邮局的所在城镇编号为k的k以前的所有的城镇距离最近的邮局的最小距离和(TM自己给自己搞了个这么绕的状态。。)
那么有DP[i][j][i] = MIN{DP[i-1][j-1][k] + dis[k][i]}其中k<i
DP[i][j][k] = DP[i-1][j][k]
其中,dis[k][i]表示[k, i]这个区间里的所有城镇距离 邮局k 和 邮局i 的最小值的和,即:
dis[i][j] = sum{ MIN(x[k]-x[i], x[j]-x[k]) } i<=k<=j
考虑边界条件,对于DP[i][j][k],由于如果前i个城镇一个都不放,那么k取任意值都是不合法的(因为我是这么表示状态的2333333..),所以对于任意的i,先算一边j=1的情况,即DP[i][1][k] = dis[0][k],默认的x[0] = -INF
最后的答案就是: MIN{DP[V][P][k] + dis[k][V]} P <=k<=V
其他的按照上面的思路敲就是了,然后我就愉快的提交了,TM居然告诉我内存超了300 × 300 × 30 啊,怎么会超!!!TM内存只给了10000,没办法就只好将第一维大小压缩到2(因为当前的i只与i-1有关。。)
79ms,O(V^3),我愉快的笑了
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <cstdio> 9 #include <cctype> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define INF 100000000 16 #define inf (-((LL)1<<40)) 17 #define lson k<<1, L, mid 18 #define rson k<<1|1, mid+1, R 19 #define mem0(a) memset(a,0,sizeof(a)) 20 #define mem1(a) memset(a,-1,sizeof(a)) 21 #define mem(a, b) memset(a, b, sizeof(a)) 22 #define FOPENIN(IN) freopen(IN, "r", stdin) 23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout) 24 template<class T> T CMP_MIN ( T a, T b ) { return a < b; } 25 template<class T> T CMP_MAX ( T a, T b ) { return a > b; } 26 template<class T> T MAX ( T a, T b ) { return a > b ? a : b; } 27 template<class T> T MIN ( T a, T b ) { return a < b ? a : b; } 28 template<class T> T GCD ( T a, T b ) { return b ? GCD ( b, a % b ) : a; } 29 template<class T> T LCM ( T a, T b ) { return a / GCD ( a, b ) * b; } 30 template<class T> T SWAP( T& a, T& b ) { T t = a; a = b; b = t; } 31 32 //typedef __int64 LL; 33 typedef long long LL; 34 const int MAXN = 255; 35 const int MAXM = 110000; 36 const double eps = 1e-12; 37 38 int V, P; 39 int x[310], DP[3][35][310]; 40 int dis[310][310], pre[310]; 41 42 void initDis() 43 { 44 mem0(dis);mem0(pre); 45 for(int i=1;i<=V;i++) 46 for(int j=i;j<=V;j++) 47 for(int k=i;k<=j;k++) 48 dis[i][j] += MIN(x[k]-x[i], x[j]-x[k]); 49 for(int i=1;i<=V;i++)for(int j=i;j>=1;j--) 50 pre[i] += x[i] - x[j]; 51 } 52 53 int main() 54 { 55 //FOPENIN ( "in.txt" ); 56 //FOPENOUT("out.txt"); 57 while(~scanf("%d %d", &V, &P)) 58 { 59 for(int i=1;i<=V;i++) 60 scanf("%d", &x[i]); 61 initDis(); 62 for(int i=0;i<2;i++) 63 for(int j=0;j<=MIN(i,P);j++) 64 for(int k=0;k<=i;k++){ 65 DP[i][j][k] = INF; 66 } 67 int now = 0; 68 for(int i=1;i<=V;i++) 69 { 70 now = !now; 71 int s = 0; 72 for(int j=1;j<=i;j++) DP[now][1][j] = pre[j]; 73 for(int j=2;j<=MIN(i, P); j++) 74 { 75 DP[now][j][i] = INF; 76 for(int k=j-1;k<i;k++)if(DP[!now][j-1][k] != INF) 77 { 78 DP[now][j][i] = MIN(DP[now][j][i], DP[now][j-1][k] + dis[k][i]); 79 } 80 for(int k=j;k<i;k++) DP[now][j][k] = DP[!now][j][k]; 81 } 82 } 83 int ans = INF; 84 for(int k=P;k<=V;k++)if(DP[now][P][k] != INF) 85 { 86 int s = 0; 87 for(int j = k + 1; j <= V; j ++ ) s += x[j] - x[k]; 88 ans = MIN(ans, DP[now][P][k] + s); 89 } 90 printf("%d\n", ans); 91 } 92 return 0; 93 }