UVA 1474(dp + 추리)

5012 단어
Flatland government is building a new highway that will be used to transport weapons from its main weapon plant to the frontline in order to support the undergoing military operation against its neighbor country Edgeland. Highway is a straight line and there are n construction teams working at some points on it.
During last days the threat of a nuclear attack from Edgeland has significantly increased. Therefore the construction office has decided to develop an evacuation plan for the construction teams in case of a nuclear attack. There are m shelters located near the constructed highway. This evacuation plan must assign each team to a shelter that it should use in case of an attack.
Each shelter entrance must be securely locked from the inside to prevent any damage to the shelter itself. So, for each shelter there must be some team that goes to this shelter in case of an attack. The office must also supply fuel to each team, so that it can drive to its assigned shelter in case of an attack. The amount of fuel that is needed is proportional to the distance from the team's location to the assigned shelter. To minimize evacuation costs, the office would like to create a plan that minimizes the total fuel needed.
Your task is to help them develop such a plan.

Input 


The input file contains several test cases, each of them as described below.
The first line of the input file contains n -- the number of construction teams (1n4000). The second line contains n integer numbers - the locations of the teams. Each team's location is a positive integer not exceeding 109, all team locations are different.
The third line of the input file contains m -- the number of shelters (1mn).
The fourth line contains m integer numbers -- the locations of the shelters. Each shelter's location is a positive integer not exceeding 109, all shelter locations are different.
The amount of fuel that needs to be supplied to a team at location x that goes to a shelter at location y is equal to | x - y|.

Output 


For each test case, the output must follow the description below.
The first line of the output file must contain z -- the total amount of fuel needed. The second line must contain n integer numbers: for each team output the number of the shelter that it should be assigned to. Shelters are numbered from 1 to m in the order they are listed in the input file.

Sample Input 

3 
1 2 3 
2 
2 10

Sample Output 

8 
1 1 2

제목: 한 도로에서 n개의 시공팀, m개의 피난처, 각 피난처에 최소한 한 명의 사람을 요구하고 현재 시공팀을 피난처에 분배하여 피난할 때 필요한 최소 이동 총 거리를 묻는다.
사고방식: dp[i][j]는 전 i개 시공팀을 대표하여 전 m개 피난처에 넣는다. 각 피난처마다 최소한 한 팀의 사람이 있기 때문에 dp[i][j]=min(dp[i-1][j-1]+abs(a[i]-b[j]), dp[i-1][j]+abs(min(a[i]-b[k])).dp[i-1][j]+abs(min(a[i]-b[k]) 때문에 a와 b 사이의 거리가 가장 작으면 시간의 복잡도가 증가한다. 그러나 사실 a, b를 모두 작은 것에서 큰 것으로 정렬한 후에 a[i]는 반드시 b[j]를 넣어야 한다. 만약에 a[i]>=b[j], a[i]에서 b[j]로 가장 짧을 것이다. 왜냐하면 b[k그래서 마지막으로 dp[i][j]=min(dp[i-1][j-1], dp[i-1][j])+abs(a[i]-b[j])로 결론을 내렸다.그리고 이 문제의 수조는 4000*4000으로 열 수 없으며 스크롤 수조로 최적화해야 한다.
코드:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
const long long INF = 1e17;
const int N = 4005;
int n, m, i, j, ans[N];
long long dp[2][N]; 
int path[N][N];
struct Q {
	int v, id;
} a[N], b[N];

bool cmp(Q a, Q b) {
	return a.v < b.v;
}

void print(int n, int m) {
	if (n == 0 || m == 0) return;
	ans[a[n].id] = b[m].id;
	print(n - 1, m - path[n][m]);
}

long long solve() {
	for (i = 1; i <= m; i++)
		dp[0][i] = INF;
	dp[0][0] = 0;
	for (i = 1; i <= n; i++) {
		int now = i % 2;
		int pre = 1 - now;
		for (j = 0; j <= m; j++)
			dp[now][j] = INF;
		for (j = 1; j <= m && j <= i; j++) {
			if (dp[pre][j - 1] < dp[pre][j]) {
				dp[now][j] = dp[pre][j - 1] + abs(a[i].v - b[j].v);
				path[i][j] = 1;
			}
			else {
				dp[now][j] = dp[pre][j] + abs(a[i].v - b[j].v);
				path[i][j] = 0;
			}
		}
	}
	return dp[n%2][m];
}

int main() {
	while (~scanf("%d", &n)) {
		for (i = 1; i <= n; i++) {
			scanf("%d", &a[i].v);
			a[i].id = i;
		}
		scanf("%d", &m);
		for (i = 1; i <= m; i++) {
			scanf("%d", &b[i].v);
			b[i].id = i;
		}
		sort(a + 1, a + 1 + n, cmp);
		sort(b + 1, b + 1 + m, cmp);
		printf("%lld
", solve()); print(n, m); for (i = 1; i < n; i++) printf("%d ", ans[i]); printf("%d
", ans[n]); } return 0; }

좋은 웹페이지 즐겨찾기