【codevs1962】马棚问题

题目描述 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
#include
#include
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



你可能感兴趣的:(codevs,dp,题解,dp)