正文

Zoj 2278 Fight for Food2008-02-11 14:50:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/cruxd/32630.html

分享到:

2745991 2008-02-07 15:05:00 Accepted 2278 C++ 00:00.68 1708K C.D. 感谢W111(WCY)同学的解题报告。 相当出色的DP优化题。类似于最大不下降子序列,一般有O(N2)的简单算法。但N>30000,故需要优化。原先的算法中,设F(i)= 到第i只老鼠时捕捉到的最大数目,F(i)= max(F(j)+1),j从1到i-1,假如在时限内能从第i到第j只老鼠出现的方格。这里可以预先使用BFS,用time[rati.i][rati.j][ratj.i][ratj.j]来记录从i到j的最小时间,并加以判断。为了优化时间,首先进行预处理,把不可能捕捉到的老鼠删除,把从每一点访问所有点至少需要的时间maxtime[rati.i][rati.j]记录下来。然后把老鼠出现的时间排序。当j从1到i-1访问的时候,可以看到有一些老鼠和当前i的时间相差太多,必然可以访问。这样只要把这些老鼠的最大值+1即可。这些老鼠是:设老鼠j到老鼠i的时间大于i访问所有点的最大时间maxtime。那么,对于k<j,也必然大于maxtime。这样就成功剪去大部分时间。WA了无数遍,终于发现漏了一种不可能捕捉到老鼠的状况。   另外试验一下代码格式     /**//*    作者:    Crux.D    日期:    2008-2-11    描述:    动态规划的优化*/#include <iostream>#include <string>#include <algorithm>using namespace std;#define check(x, y) (x >= 0 && y >= 0 && x < N && y < M && map[x][y] == 0)int N, M, P, map[10][10], dist[10][10][10][10], max_time[10][10], opt[30010], f[30010];int dir[4][2] ={    { 0, 1 }, { 0, -1 }, { 1, 0 }, { - 1, 0 }};  typedef struct{    int i, j, t;} Rat;Rat r[50001];Rat cx;Rat q[101];//保存老鼠出现的队列bool cmp ( const Rat &a, const Rat &b ){    return a.t < b.t;}void init ();int dp ();void BFS ( int, int );int main (){    //freopen ( "in.txt", "r", stdin );    while ( scanf ( "%d %d", &N, &M ) != EOF )    {        init ();        //pt ();        printf ( "%d\n", dp () );    }    return 0;}void init (){    int i, j;    char ch[11];    memset ( dist, 0xff, sizeof ( dist ) );    memset ( max_time, 0x00, sizeof ( max_time ) );    memset ( map, 0x00, sizeof  ( map ) );    gets ( ch );    for ( i = 0; i < N; i ++ )    {        gets ( ch );        for ( j = 0; j < M; j ++ )        {            if ( ch[j] == 'L' )            {                cx.i = i, cx.j = j;            }            if ( ch[j] == '#' )            {                map[i][j] = 1;            }        }    }    BFS ( cx.i, cx.j );    for ( i = 0; i < N; i ++ )    {        for ( j = 0; j < M; j ++ )        {            if ( dist[cx.i][cx.j][i][j] > 0 )            {                BFS ( i, j );            }        }    }       r[0].i = cx.i, r[0].j = cx.j, r[0].t = 0;    for ( scanf ( "%d", &j ), i = 0, P = 0; i < j; i ++ )    {        P ++;        scanf ( "%d%d%d", &r[P].i, &r[P].j, &r[P].t );        r[P].i --, r[P].j --;        if ( dist[cx.i][cx.j][r[P].i][r[P].j] < 0 )        {            P --;        }        else if ( r[P].t < dist[cx.i][cx.j][r[P].i][r[P].j] )        {            P --;        }    }        sort ( r, r + P + 1, cmp );}void BFS ( int i, int j ){    int op, ed, ii, jj, k;    for ( op = -1, ed = 0, q[0].i = i, q[0].j = j, dist[i][j][i][j] = 0; op ++ < ed; )    {        for ( k = 0; k < 4; k ++ )        {            ii = q[op].i + dir[k][0], jj = q[op].j + dir[k][1];            if ( check ( ii, jj ) && dist[i][j][ii][jj] < 0 )            {                q[++ ed].i = ii; q[ed].j = jj;                dist[i][j][ii][jj] = dist[i][j][q[op].i][q[op].j] + 1;            }        }    }    max_time[i][j] = dist[i][j][q[ed].i][q[ed].j];}int dp (){    int i, j;        for ( i = 1, f[0] = opt[0] = 0; i <= P; i ++ )    {        f[i] = 0;        //if ( r[i].t >= dist[cx.i][cx.j][r[i].i][r[i].j] )  //prune        {            for ( j = i - 1; j >= 0 && r[i].t - r[j].t < max_time[r[i].i][r[i].j]; j -- )    //prune            {                if ( r[i].t - r[j].t >= dist[r[i].i][r[i].j][r[j].i][r[j].j] && f[i] < f[j] + 1 )                {                    f[i] = f[j] + 1;                }            }            if ( j >= 0 && f[i] < opt[j] + 1 )            {                f[i] = opt[j] + 1;            }        }            opt[i] = ( opt[i - 1] > f[i] ? opt[i - 1] : f[i] );    }    return opt[P];}

阅读(2499) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册