andre_joy

导航

hdu 4293

地址:http://acm.hdu.edu.cn/showproblem.php?pid=4293

题意:一行人行走,分成很多组,每个人要说出他前面和后面分别有多少个人,他自己团队的人可以忽略,问最多有多少人说真话了。

mark:学习了大牛的思路,真是没话说。。想不到……大牛的思路是dp[i][j]代表前i个人并且i+1到j个人是一个团队的时候,最多有多少人说真话。

   http://blog.csdn.net/taozifish/article/details/7985044

   我在研究了他的代码之后,发现代码可以优化,优化之后顿时有一种豁然开朗的感觉,我知道为什么会这样想了。

   dp[i]表示前i个人最多有多少人说真话,那么这一状态是无后效性的,现在要找最优子结构。

   由于初始化的时候w[i][j]是记录的都说前面是i个人,后面是j个人的人的个数,那么dp[i]的前i个人就可以分隔成dp[j](1 <= j < i)+w[j][n-i](这就是一个典型的最优子结构,想通了也就做出来了。)

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#define LL long long

using namespace std;

const int N = 510;
int n;
int w[N][N],dp[N];

int max(int a, int b) {return a > b ? a : b;}

int main()
{
    int i,j,k;
    while(~scanf("%d", &n))
    {
        memset(w, 0, sizeof(w));
        memset(dp, 0, sizeof(dp));
        for(i = 1; i <= n; i++)
        {
            scanf("%d%d", &j, &k);
            if(j+k < n)
            {
                w[j][k]++;
                if(w[j][k] > n-j-k) w[j][k] = n-j-k;
            }
        }
        for(j = 1; j <= n; j++)
            for(i = 0; i < j; i++)
                dp[j] = max(dp[i]+w[i][n-j], dp[j]);
        printf("%d\n", dp[n]);
    }
    return 0;
}

posted on 2012-09-17 20:34  andre_joy  阅读(152)  评论(0编辑  收藏  举报