1. 程式人生 > >LA 4987 背包

LA 4987 背包

b- 數組 pri logs 分析 ems 施工隊 src isp

題意:

有n個施工隊,給定他們的位置,有m個防空洞,給定位置,求將施工隊放到m個防空洞裏面,最少的總距離?

n<=4000

分析:

dp[i][j] 前 i 個施工隊,放到前 j 個防空洞裏面的最少距離;

dp(i+1,j) = min(dp(i,j),dp(i,j-1)) + dist(a[i] - b[j]);

DP采用滾動數組;

那麽,第二維的防空洞該怎麽循環呢?

因為,每個防空洞都要有,那麽這類似於背包中的容量,刷表的方式;

技術分享
#include <bits/stdc++.h>

using namespace std;

const int maxn = 4000
+5; const int inf = 0x3f3f3f3f; struct node { int d; int id; int ans; }A[maxn],B[maxn]; long long dp[maxn]; int path[maxn][maxn]; int n,m; bool cmp(node a,node b) { if(a.d==b.d) return a.id < b.id; return a.d < b.d; } void find_path(int i,int j) {
if(i) find_path(i-1,path[i][j]); A[i].ans = B[j].id; } int cmp1(node a,node b) { return a.id < b.id; } int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;i++) { scanf("%d",&A[i].d); A[i].id = i; } scanf(
"%d",&m); for(int i=0;i<m;i++) { scanf("%d",&B[i].d); B[i].id = i; } sort(A,A+n,cmp); sort(B,B+m,cmp); memset(dp,inf,sizeof(dp)); dp[0] = abs(A[0].d-B[0].d); for(int i=1;i<n;i++) { for(int j=min(m-1,i);j>=0;j--) { if(!j||dp[j]<dp[j-1]) { path[i][j] = j; dp[j] = dp[j] + abs(A[i].d-B[j].d); } else { path[i][j] = j-1; dp[j] = dp[j-1] + abs(A[i].d - B[j].d); } } } printf("%lld\n",dp[m-1]); find_path(n-1,m-1); sort(A,A+n,cmp1); for(int i=0;i<n;i++) printf("%d ",A[i].ans+1); puts(""); } return 0; }
View Code

LA 4987 背包