连接棋子(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;
}

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