URAL 1167. Bicolored Horses(二维dp或者记忆化搜索)

18 篇文章 0 订阅

这道题是啸爷做的,然后跟我商量了一下。我感觉这个刚在杭电上做过的一道题目类似,推了一下状态转移公式。无奈,水平太差,竟然推出来,没有写对。只好看了一下,虎哥和催老师的题解。虎哥用的记忆化搜索。感觉挺好的,也学着写了一下。

状态转移方程是:dp[i][j] = min(dp[i][j], dp[i-k][j-1]+(k-(num[i]-num[i-k])*(num[i]-num[i-k])))。这里i,j表示马的个数,或者是马厩的个数。因为记忆化搜索,和dp用到的d,j意思是相反的。但是,理解起来一样啊。

1167. Bicolored Horses

Time limit: 1.0 second
Memory limit: 64 MB
Every day, farmer Ion (this is a Romanian name) takes out all his horses, so they may run and play. When they are done, farmer Ion has to take all the horses back to the stables. In order to do this, he places them in a straight line and they follow him to the stables. Because they are very tired, farmer Ion decides that he doesn't want to make the horses move more than they should. So he develops this algorithm: he places the 1st P 1 horses in the first stable, the next P 2 in the 2nd stable and so on. Moreover, he doesn't want any of the  K stables he owns to be empty, and no horse must be left outside. Now you should know that farmer Ion only has black or white horses, which don't really get along too well. If there are  black horses and  j white horses in one stable, then the coefficient of unhappiness of that stable is  i*j. The total coefficient of unhappiness is the sum of the coefficients of unhappiness of every of the K stables.
Determine a way to place the  N horses into the  K stables, so that the total coefficient of unhappiness is minimized.

Input

On the 1st line there are 2 numbers:  N (1 ≤ N ≤ 500) and  K (1 ≤ K ≤ N). On the next N lines there are N numbers. The i-th of these lines contains the color of the i-th horse in the sequence: 1 means that the horse is black, 0 means that the horse is white.

Output

You should only output a single number, which is the minimum possible value for the total coefficient of unhappiness.

Sample

input output
6 3
1
1
0
1
0
1
2
DP:

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-7
#define M 10001000
#define LL __int64
//#define LL long long
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
const int maxn = 510;

using namespace std;

int dp[maxn][maxn];
int num[maxn];


int main()
{
    int n, m;
    cin >>n>>m;
    memset(num, 0 , sizeof(num));
    for(int i = 1; i <= n; i++)
    {
        cin >>num[i];
        num[i] += num[i-1];
    }
    memset(dp, INF , sizeof(dp));
    for(int i = 1; i <= n; i++)
        dp[i][1] = num[i]*(i-num[i]);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 2; j <= m; j++)
        {
            for(int k = 1; k <= i-j+1; k++)
            {
                int cnt = num[i]-num[i-k];
                dp[i][j] = min(dp[i][j], dp[i-k][j-1]+(k-cnt)*cnt);
            }
        }
    }
    cout<<dp[n][m]<<endl;
    return 0;
}

记忆化搜索:

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-7
#define M 10001000
#define LL __int64
//#define LL long long
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
const int maxn = 510;

using namespace std;

int ans[maxn][maxn];
int num[maxn];
int dp(int i, int j)
{
    if(ans[i][j] != -1)
        return ans[i][j];
    if(i == j)
    {
        ans[i][j] = 0;
        return ans[i][j];
    }
    if(i == 1)
    {
        ans[i][j] = num[j]*(j-num[j]);
        return ans[i][j];
    }
    if(i < j)
    {
        ans[i][j] = INF;
        for(int k = 1; k <= j-i+1; k++)
        {
            int cnt = num[j]-num[j-k];
            ans[i][j] = min(ans[i][j], dp(i-1, j-k)+cnt*(k-cnt));
        }
        return ans[i][j];
    }
    return ans[i][j];
}

int main()
{
    int n, m;
    cin >>n>>m;
    memset(num, 0 , sizeof(num));
    for(int i = 1; i <= n; i++)
    {
        cin >>num[i];
        num[i] += num[i-1];
    }
    memset(ans , -1, sizeof(ans));
    cout<<dp(m, n)<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值