連接棋子(DP)



問題

 

連接棋子

 

N個棋子放到了x軸座標1, 2, ..., n上。N是偶數。

其中n/2個是黑色棋子,剩下的n/2個是白色棋子。連接一個黑色棋子和白色棋子弄成一雙時,會有n/2個雙。連接一雙棋子時,會從左邊的棋子開始出發垂直往上走,然後水平往右走,接着重新垂直往下走,開拓到達右邊棋子的路。

長成這樣的 n個路不能相互重疊,也不能相互交叉。爲了能讓所有路的距離之和弄成最小,請編寫開拓n個路的程序。 這裏,距離的單位中垂直和水平都是1

圖片1的情況,可以用其他方法連接,但是上面的連接方法是最小的連接方法,距離的值爲31。圖片2的情況,也有其他的方法,但是上面的方法是最小的連接方法,距離的值爲40

限制時間 : 1.5

輸入

第一行給出表示點的個數的自然數nn 400 以下的偶數。從下一行給出以n/20 n/21構成的字符串。0是白色棋子, 1是黑色棋子。從左邊開始按順序與座標1,2, ... , n相應。

輸出

第一行輸出,路的距離之和中的最小值。

案例輸入1

10

1110100010

案例輸出1

31

案例輸入2

12

111000111000

案例輸出2

40

#include <stdio.h>
#include <algorithm>

using namespace std;

int n;
char ch[405];

int D[405][405], H[405][405];

int main(){
	scanf("%d", &n);
	scanf("%s", ch + 1);
	for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)D[i][j] = H[i][j] = 1000000;
	for (int i = 1; i <= n; i++)D[i][i - 1] = H[i][i - 1] = 0;
	for (int i = 1; i <= n - 1; i++){
		if (ch[i] == ch[i + 1])continue;
		D[i][i + 1] = 3;
		H[i][i + 1] = 1;
	}
	for (int i = 3; i<n; i += 2){
		for (int j = 1; j + i <= n; j++){
			for (int k = j; k<j + i; k += 2){
				//k -- j+i
				if (D[j][k - 1] != -1 && D[k + 1][j + i - 1] != -1 && ch[k] != ch[j + i]){
					D[j][j + i] = min(D[j][j + i], D[j][k - 1] + D[k + 1][j + i - 1] + H[k + 1][j + i - 1] * 2 + 2 + (j + i - k));
					H[j][j + i] = min(H[j][j + i], max(H[j][k - 1], H[k + 1][j + i - 1] + 1));
				}
			}
		}
	}
	printf("%d\n", D[1][n]);
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章