马棚问题

来源:互联网 发布:php nginx 返回截断 编辑:程序博客网 时间:2024/04/30 10:44

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

Input

多个测试组, 
每组测试第一行有2个数字:n( 1 <= n <= 500)和k( 1 <= k <= n). 
接下来的n行是n个数,在这些行中的第i行代表队列中的第i匹马的颜色:1意味着马是黑色的,0则是白色的。 
处理到结束。

Output

对每组测试数据输出一行,只输出一个数字,代表系数总和可能达到的最小值

Sample Input

6 3110101

Sample Output

2

代码如下:

#include "stdio.h"#define MAX 510#define min(a,b) a>b?b:a#define INFINITY 10000000struct hores{int black;int white;}hores[MAX];int N,K;int DFS(int k,int x,int y);int main(){int i,current;//1为黑 0为白hores[0].black=0;hores[0].white=0;scanf("%d%d",&N,&K);for(i=1;i<=N;i++){scanf("%d",&current);if(current){hores[i].black = hores[i-1].black + 1;hores[i].white = hores[i-1].white;}else{hores[i].white = hores[i-1].white + 1;hores[i].black = hores[i-1].black;}}for(i=1;i<=N;i++)printf("%d %d\n",hores[i].white,hores[i].black);printf("%d\n",DFS(1,1,K));return 0;}int DFS(int k,int x,int y){int i,MIN=INFINITY;if(k == K)return (hores[N].white - hores[x-1].white)*(hores[N].black - hores[x-1].black);for(i = x; i<=N-y+1;i++)MIN=min(MIN,DFS(k+1,i+1,y-1)+(hores[i].white-hores[x-1].white)*(hores[i].black - hores[x-1].black));return MIN;}

区间dp,不足之处做不了记忆画搜索,属于暴力搜索的一种。

优化后,添加了记忆化搜索:

/*记忆化搜索*/#include "stdio.h"#define MAX_N 510#define INFINITY 10000000struct hores{int black;int white;}hores[MAX_N];int dp[MAX_N][MAX_N]={0};//dp[n][k]代表从1-n的马匹放在前k个马鹏最小值int main(){int i,current,j,k,K,N;//1为黑 0为白hores[0].black=0;hores[0].white=0;scanf("%d%d",&N,&K);for(i=1;i<=N;i++)for(j=1;j<=N;j++)dp[i][j]=INFINITY;//初始化dpfor(i=1;i<=N;i++){scanf("%d",¤t);if(current){hores[i].black = hores[i-1].black + 1;hores[i].white = hores[i-1].white;}else{hores[i].white = hores[i-1].white + 1;hores[i].black = hores[i-1].black;}}for(i=1;i<=N;i++)dp[i][1]=(hores[i].black-hores[0].black)*(hores[i].white-hores[0].white);//把1-i的马匹全部放在第1个马棚for(i=1;i<=N;i++)//长度for(k=2;k<=K;k++)//马棚for(j=k-1;j<=i-1;j++)//切割点if(dp[i][k] > dp[j][k-1] + (hores[i].black-hores[j].black)*(hores[i].white-hores[j].white)) dp[i][k] = dp[j][k-1] + (hores[i].black-hores[j].black)*(hores[i].white-hores[j].white);printf("%d\n",dp[N][K]);return 0;}

dp[n][k]表示在1-n马匹放在前k个马棚的最小不愉快系数

如题要求的是把6匹马放在3个马棚产生的不愉快系数最小

123456110101
比如3做为切割点那就分为123110
456101那么意味把(1-3)放在前两个马棚,那么问题就6匹马放在3个马棚转为将(1-3)匹马如何放在两个马棚的问题,因为(4-6)的马是一个定量。如下



切点为2

123110那么现在就剩下(1-3)的马该怎么放,按照上面也可以将3匹马放在前两个马棚转为(1-2)的马匹如何放在前一个马棚的问题

..........................................

根据上面可以找出状态方程:

dp[i][k] = min(dp[i][k],dp[j][k-1] + hores[i]-hores[j]);(1<=i<=N,2<=k<=N,k-1<=j<=i-1)


0 0
原创粉丝点击