农场主

问题描述:
小张是一个养马农场的农场主,他要把N只马分配到K个马房里,放置的规则是:第1 到 第Pi只马放入第一个马房,第Pi+1 到第Pk只放入第二个马房,…以此类推。此外对于每一个马房都有一个叫做“不高兴系数”,即白色马的数量*黑色马的数量。你的任务是合理地分配这N只马,使得它所有马房的“不高兴系数”和最小。
数据输入:
从文件farmer.in中读入数据,文件中第一行有 2 个整数: N ( 1 <= N <= 500 ) 和 K ( 1 <= K <= N)。接下来的N行有N个数。第 I 行为第 I 只马的颜色: 1 是黑色, 0 是白色。
数据输出:
将结果输出到文件farmer.out中,其结果为最小的“不高兴系数”的总和。
输入输出样例:
farmer. in
6 3
1
1
0
1
0
1
farmer.out
2

.
.
.
.
.
分析
用f[i,j]表示用i个马房装j匹马的最小不高兴系数
首先要预处理第i匹马时有多少只白马,多少只黑马,接着算出一个马房装1~n匹马的不高兴系数为多少。
接着DP,用少马房装少马去更新多马房装多马。
具体实现就是用i枚举马房;j枚举要马;l枚举比j小的马;少马房就用i-1。
故可以用f[i-1,l]来更新f[i,j],注意更新时装多了马后,要累加产生的不高兴系数
动态转移方程:f[i,j]:=f[i-1,l]+(b[j]-b[l])*(w[j]-w[l])

.
.
.
.
.
程序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

int n,k,w[1000],b[1000],f[510][510];

int main()
{
	freopen("farmer.in","r",stdin);
	freopen("farmer.out","w",stdout);
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		if (x==1)
		{
			w[i]=w[i-1];
			b[i]=b[i-1]+1;
		} else
		{
			w[i]=w[i-1]+1;
			b[i]=b[i-1]; 
		}
	}
	for (int i=1;i<=n;i++)
		f[1][i]=w[i]*b[i];
	if (k==1)
	{
		printf("%d",f[1][n]);
		fclose(stdin);
		fclose(stdout);
		return 0;
	}
	for (int i=2;i<=k;i++)
		for (int j=i;j<=n-k+i;j++)
		{
			int t=2147483647;
			for (int l=i-1;l<=j-1;l++)
			{
				f[i][j]=f[i-1][l]+(b[j]-b[l])*(w[j]-w[l]);
				t=min(t,f[i][j]);
			}
			f[i][j]=t;
		}
	printf("%d",f[k][n]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2019-05-08 19:43  银叶草  阅读(267)  评论(0编辑  收藏  举报
Live2D