题目描述
每天,小明和他的马外出,然后他们一边跑一边玩耍。当他们结束的时候,必须带所有的马返回马棚,小明有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 ",f[n][k]); 41 return 0; 42 }