RQNOJ273 马棚问题

 

题目描述

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

输入格式

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

输出格式

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

 
样例输入

6 3 //{6匹马,3个马棚}
1  //    {第1匹马为黑马}
1
0    //{第3匹马为白马}
1
0
1

样例输出

2

 

枚举分组区间进行转移。

 

 1 /*by SilverN*/
 2 //WA 1:j每次从0开始循环,T掉一个点 
 3 //       改成从c-1开始循环以后,904ms卡过 
 4 #include<algorithm>
 5 #include<iostream>
 6 #include<cstring>
 7 #include<cstdio>
 8 #include<cmath>
 9 using namespace std;
10 const int mxn=800;
11 int read(){
12     int x=0,f=1;char ch=getchar();
13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 int w[mxn],b[mxn];
18 int f[mxn][mxn];
19 int n,k;
20 int main(){
21     memset(f,0x2f,sizeof f);
22     int i,j;
23     n=read();k=read();
24     int x;
25     for(i=1;i<=n;i++){
26         x=read();
27         if(x)b[i]++;
28         else w[i]++;
29         b[i]+=b[i-1];
30         w[i]+=w[i-1];
31     }
32     f[0][0]=0;
33     for(int c=1;c<=k;++c){
34         for(i=c;i<=n;++i){
35             for(j=c-1;j<i;++j){
36                 f[i][c]=min(f[i][c],f[j][c-1]+(b[i]-b[j])*(w[i]-w[j]));
37             }
38         }
39     }
40     printf("%d\n",f[n][k]);
41     return 0;
42 }

 

posted @ 2016-10-10 15:41  SilverNebula  阅读(350)  评论(0编辑  收藏  举报
AmazingCounters.com