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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值