二色马 解题报告

来源:互联网 发布:三类医疗器械 淘宝 编辑:程序博客网 时间:2024/05/21 09:27

【动态规划基础】二色马

Time Limit:1000MS  Memory Limit:65536K

Description

  一个农夫要把n只马分配到k个马房里,放置的规则是:第1 到 第pi只马放入第一个马房,第pi+1 到第pk只放入第二个马房,......,以此类推。此外对于每一个马房都有一个叫做“不高兴系数”,即白色马的数量*黑色马的数量。你的任务是合理地分配这n只马,使得它所有马房的“不高兴系数”和最小。

Input

  从文件horses.in中读入数据,文件中第一行有 2 个整数: n ( 1 <= n <= 500 ) 和 k ( 1 <= k <= n)。接下来的n行有n个数。第 i 行为第 i 只马的颜色: 1 是黑色, 0 是白色。

Output

  将结果输出到文件horses.out中,其结果为最小的“不高兴系数”的总和。

Sample Input

6 3
1
1
0
1
0
1

Sample Output

2


经典的区间动规。

用f[i][j]表示前i只马放到前j个马房的最小“不高兴系数”,则f[i][j]=min(f[i][j],f[k][j]+a[k+1][j]),其中a[i][j]表示将i到j匹马放到同一个马房的“不高兴系数”。

a[i][j]需要预处理出来,详见代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int f[501][501];int a[501][501];int c[501];int n,t;int main(){scanf("%d%d",&n,&t);for (int i=1;i<=n;i++) scanf("%d",&c[i]);for (int i=1;i<n;i++){int l=0;int r=0;if (c[i]==1) l++; else r++;for (int j=i+1;j<=n;j++){if (c[j]==1)l++;else r++;a[i][j]=l*r;}}memset(f,0x7f7f,sizeof(f));f[0][0]=0;for (int i=1;i<=n;i++)for (int j=1;j<=min(i,t);j++)for (int k=0;k<i;k++)f[i][j]=min(f[i][j],f[k][j-1]+a[k+1][i]);printf("%d",f[n][t]);}
显然a数组符合区间单调性,因此可以用四边形不等式优化。(见:http://blog.csdn.net/weixin_39872717/article/details/78765532)

代码:

#include<cstdio>#include<cstring>using namespace std;int s[501][501];int f[501][501];int a[501][501];bool c[501];int n,t;int main(){scanf("%d%d",&n,&t);for (int i=1;i<=n;i++) scanf("%d",&c[i]);for (int i=1;i<n;i++){int l=0;int r=0;if (c[i]==1) l++; else r++;for (int j=i+1;j<=n;j++){if (c[j]==1)l++;else r++;a[i][j]=l*r;}}for (int i=1;i<=n;i++) {f[i][1]=a[1][i];s[i][1]=1;}for (int j=2;j<=t;j++){s[n+1][j]=n;for (int i=n;i>=j;i--){f[i][j]=2147483647;for (int k=s[i][j-1];k<=s[i+1][j];k++)if (f[k-1][j-1]+a[k][i]<f[i][j]){f[i][j]=f[k-1][j-1]+a[k][i];s[i][j]=k;}}}printf("%d",f[n][t]);}

原创粉丝点击