Armchairs CodeForces - 1525D 【DP】

There are n armchairs, numbered from 1 to n from left to right. Some armchairs are occupied by people (at most one person per armchair), others are not. The number of occupied armchairs is not greater than n/2.
For some reason, you would like to tell people to move from their armchairs to some other ones. If the i-th armchair is occupied by someone and the j-th armchair is not, you can tell the person sitting in the i-th armchair to move to the j-th armchair. The time it takes a person to move from the i-th armchair to the jj-th one is |i - j|minutes. You may perform this operation any number of times, but these operations must be done sequentially, i. e. you cannot tell a person to move until the person you asked to move in the last operation has finished moving to their destination armchair.

You want to achieve the following situation: every seat that was initially occupied must be free. What is the minimum time you need to do it?

Input

The first line contains one integer nn (2≤n≤5000) — the number of armchairs.

The second line contains n integers a1, a2, ……, an(0≤ai ≤1).

ai=1 means that the ii-th armchair is initially occupied, ai = 0means that it is initially free. The number of occupied armchairs is at most n/2.

Output

Print one integer — the minimum number of minutes you have to spend to achieve the following situation: every seat that was initially occupied must be free.

Sample 1

Input

7
1 0 0 1 0 0 1

Output

3

Sample 2

Input

6
1 1 1 0 0 0

Output

9

Sample 3

Input

5
0 0 0 0 0

Output

0

题意

有一排椅子,其中有n/2的椅子有人坐(值为1),其余为0,要求让每个从坐的椅子都转移到没人坐过的椅子,每个人只能转移一次,且每次操作的代价为abs ( i − j ) ,要求总代价最小。

代码

#include "stdio.h"
#include "algorithm"
#include "math.h"
#include "string.h" 
using namespace std;
int a[5009];
int b[5009];
int dp[5000][5000];
//dp[i][j]:第i个人移到第j个椅子和前面i-1个人移到j之前的空椅子的总代价最小
int mmin[5000][5000];
int main()
{
	int n,s=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int k;
		scanf("%d",&k);
		if(k) a[++a[0]]=i;//这儿的a[0]记录着a数组的长度 
		else  b[++b[0]]=i;//这儿的b[0]记录着b数组的长度
//a[1]记录着第一把被人坐的椅子的位子……
//b[1]记录着的一把没人坐的椅子的位子…… 
		s+=k;
	}
	if(s==0)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=a[0];i++)
	for(int j=i;j<=b[0];j++)
	{
//注意,这里j至少从i开始,因为如果选到更加前面的数,那么就会产生错误。
		if(i==j)
			dp[i][j]=dp[i-1][j-1]+abs(a[i]-b[j]);
		else
			dp[i][j]=min(dp[i-1][j-1]+abs(a[i]-b[j]),dp[i][j-1]);
	}
	printf("%d",dp[a[0]][b[0]]);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值