【codevs1962】马棚问题

245 篇文章 0 订阅

题目描述 Description

每天,小明和他的马外出,然后他们一边跑一边玩耍。当他们结束的时候,必须带所有的马返回马棚,小明有K个马棚。他把他的马排成一排然后跟随它走向马棚,因为他们非常疲劳,小明不想让他的马做过多的移动。因此他想了一个办法:将马按照顺序放在马棚中,后面的马放的马棚的序号不会大于前面的马放的马棚的序号。而且,他不想他的K个马棚中任何一个空置,也不想任何一匹马在外面。已知共有黑、白两种马,而且它们相处得并不十分融洽。如果有i个白马和j个黑马在一个马棚中,那么这个马棚的不愉快系数将是i*j。所有k个马棚不愉快系数的和就是系数总和。确定一种方法把n匹马放入k个马棚,使得系数总和最小

输入描述 Input Description

输入:在第一行有两个数字:n(1≤n≤500)和k(1≤k≤n)。在接下来的n行是n个数。在这些行中的第i行代表队列中的第i匹马的颜色:1意味着马是黑色的,0意味着马是白色的。 

输出描述 Output Description

输出:只输出一个单一的数字,代表系数总和可能达到的最小值

样例输入 Sample Input

6 3

1

1

0

1

0

样例输出 Sample Output

2

【题解】

和乘积最大有点像,也是一个区间dp,状态可以表示为把前i个数分成j个部分。

然后可以把问题转化为求前面几个数分成j-1个部分,然后再加上最后一部分(其实不就是j部分么)

即f[i][k]=min(f[i][k],f[j][k-1]+anger[j+1][i]);

预先处理出来怒气值。

【代码】

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,k1;
struct hp{
	int x,y;
}s[505];
int f[505][505],anger[505][505],a[505];
int main(){
	scanf("%d%d",&n,&k1);
	memset(f,127/3,sizeof(f));
	for (int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		s[i].x=s[i-1].x;
		s[i].y=s[i-1].y;
		if (a[i]==0) s[i].x++;
		else s[i].y++;
	}
	for (int i=1;i<n;++i)
	  for (int j=i+1;j<=n;++j)
	    anger[i][j]=(s[j].x-s[i-1].x)*(s[j].y-s[i-1].y);
	for (int i=1;i<=n;++i) f[i][1]=anger[1][i];
	for (int k=1;k<=k1;++k)
	  for (int i=k;i<=n;++i)
	    for (int j=k;j<=i;++j)
	      f[i][k]=min(f[i][k],f[j][k-1]+anger[j+1][i]);
	printf("%d\n",f[n][k1]);
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值