[UVA][dp] 976 - Bridge Building
Problem E - Bridge Building
Against the city's gleaming spires,
Above the ships that ply the stream,
A bridge of haunting beauty stands -
Fulfillment of an artist's dream
(D. B. Steinman)
Algorithm city is crossed by the beautiful Complexity River. Up until now, the only possible way to travel from one bank (margin) of the river to the other is by boat. This is very negative for the city economics and therefore the mayor has decided to build a series of bridges to connect the two parts of the city, lying on different banks of the river.
He has a fixed number of bridges to build, but in order to save the maximum amount of money he wishes to build the bridges has short as possible. However, since he wants to really help the citizens, the bridges must not be to close together, in order to have them splitted all over the city.
The mayor has asked for your help, and has given you the map of the part of city with that is near the river. To simplify, this map can be seen as a grid of chars. '#' means a piece of terrain and '.' means water. So, for example, a map could be something like:
#################### ..######........##.. ....##.............. .................... .................... .................#.. ..######........##.. ####################
Figure 1 - An example of a valid map
You can be sure that the map will always have terrain-only on the first and last rows, and that those pieces of terrain correspond to different banks. There will be no islands in the river, and all terrain will either be connected to the north or south bank. We consider a piece of terrain to be connected to another if they are adjacent, that is, if they are next to each other horizontally or vertically (but not diagonally). You can also be sure that on the same column of the grid map, there will never be a south piece of the bank above a north one. However, small lakes (that do not belong to the river) can exist inside banks, as exemplified in figure 2.
############### .#..#.......#.. .####......##.. .####.......... .#........##... ..........#.... ###############
Figure 2 - Another example of a valid map
The Algorithm City mayor is very old fashioned and has decided that the bridges to build must only be built in the north-south direction (vertically, in the grid). So, for example, imagine that the mayor would like to build 3 bridges, that must be separated at least by 4 positions, on the map of the figure 1. A solution that would minimize the length of the bridges would be the one in figure 3, where 'B' represents a bridge.
#################### ..######........##.. ..B.##.B.........B.. ..B....B.........B.. ..B....B.........B.. ..B....B.........#.. ..######........##.. ####################
Figure 3 - A solution for the map of figure 1
Note that the first two bridges in the solution are exactly separated by 4 spaces as required, and could not be more close. If we measure the length of the bridges built by squares in the grid, we can say that the total length used was 11 (4+4+3). Any other way of building the bridges in this map would give more total length and therefore would be worse.
The Problem
Given a grid map as specified above, a number of bridges to build and the minimum space (on columns) that should separate the bridges, your task is to calculate the best positions to build the bridges in order to minimize their total length, and print the total length of the bridges in that best arrangement.
Input
The input file contains several test cases, each of them as describes below.The first line of input contains two integers, R and C, representing respectively the numbers of rows and the number of columns of the grid map (5 ≤ R,C ≤ 1000).
Then comes a line with two integers, B and S, where B represents the number of bridges to build (1 ≤ B &le 100) and S the minimum space (in columns) that should separate bridges.
After that come exactly R lines, each one with C chars, that represent the map. This map obeys to the rules described above and only has '#' or '.'.
Output
For each test case, the output should contain a single line, with an integer representing the total length of bridges to build in the solution that minimizes this same total, as described above.
There will always be a way to build the bridges.
Sample Input
8 20 3 4 #################### ..######........##.. ....##.............. .................... .................... .................#.. ..######........##.. #################### 7 15 2 8 ############### .#..#.......#.. .####......##.. .####.......... .#........##... ..........#.... ###############
Sample Output
11 2
2006 Programming Contest of Porto University
Round 3, 11th of October of 2006
(Author: Pedro Ribeiro - DCC/FCUP)
題目描述:
在一個 R*C 的地圖中,只有上(北)方陸地和下(南)方陸地,打算建造 B 座橋梁,
保證不會存在有北方陸地在南方陸地的南方,即不會有螺旋的樣子。
而每座橋梁只會筆直地由南到北,橋梁與橋梁之間至少間隔 S 格。
問最少成本(每座橋梁的長度總和)為何?
題目解法:
首先先找到每個位置的橋梁的最少成本。
然後 dp[i][j] 表示在位置 i 時,已經建造了 j 座橋梁。
此時 dp[i][j] = cost + min(dp[k][j-1]), 其中 k < i-S
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
char g[1005][1005], used[1005][1005];
int dp[1005][1005], supdp[1005];
int north[1005], south[1005];
int R, C, B, S;
void color(int x, int y, int flag) {
queue<int> X, Y;
int tx, ty, i;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
X.push(x), Y.push(y);
while(!X.empty()) {
x = X.front(), X.pop();
y = Y.front(), Y.pop();
if(flag)
south[y] = min(south[y], x);
else
north[y] = max(north[y], x);
for(i = 0; i < 4; i++) {
tx = x+dx[i], ty = y+dy[i];
if(tx < 0 || ty < 0 || tx >= R || ty >= C)
continue;
if(used[tx][ty] || g[tx][ty] == '.')
continue;
used[tx][ty] = 1;
X.push(tx), Y.push(ty);
}
}
}
int main() {
int i, j, k;
while(scanf("%d %d %d %d", &R, &C, &B, &S) == 4) {
for(i = 0; i < R; i++)
scanf("%s", &g[i]);
for(i = 0; i < C; i++)
north[i] = -0xfffffff, south[i] = 0xfffffff;
memset(used, 0, sizeof(used));
for(i = 0; i <= B; i++)
supdp[i] = 1000000000;
color(0, 0, 0);
color(R-1, 0, 1);
supdp[0] = 0;
for(i = 0; i < C; i++) {
if(i > S) {
for(j = 1; j <= B; j++)
supdp[j] = min(supdp[j], dp[i-S-1][j]);
}
int cost = south[i]-north[i]-1;
for(j = 1; j <= B; j++) {
dp[i][j] = supdp[j-1]+cost;
}
}
int ret = 0xfffffff;
for(i = 0; i < C; i++)
ret = min(ret, dp[i][B]);
printf("%d\n", ret);
}
return 0;
}