zoukankan      html  css  js  c++  java
  • hdu 1876(dp)

    表示这题坑了我很久,我拿到题目马上想到的是用记忆化搜索做,  然后发现不是很好实现 ,然后又想了一种 半记忆化+BFS 的东西,当时分析了下发现可行。 然后写了很久, 最后死都过不了。  然后看了别人的发现别人用的是dp解法,和我的非常类似,然后我用dp那样写发现能过, 最后调试了一晚上后终于发现了,用BFS还是难是实现。 有一些数据用bfs做会错。 

    以前总是以为用dp能写的东西,那记忆化搜索也会很好写, 今天终于发现不用的方法还是要因题而议 ! , 所以以后别看这能用搜索做就立马什么都不想就用搜索做。

    机器人系列2

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 866    Accepted Submission(s): 153


    Problem Description
    这又是一个简单的游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m)。游戏的规则描述如下:
    1.机器人一开始在棋盘的起始点(1,1)并有起始点所标有的能量。
    2.机器人只能向右或者向下走,并且每走一步消耗一单位能量。
    3.只有当机器人消耗完能量时才能获得相应格子上的能量。
    请问机器人到达终点的过程中最多有几次完全消耗完能量,消耗完这么多次能量的方式有几种。
     
    Input
    输入
    第一行输入一个整数T,表示数据的组数。
    对于每一组数据第一行输入两个整数n,m(1 <= n,m <= 100)。表示棋盘的大小。接下来输入n行,每行m个整数e(0 <= e < 20)。
     
    Output
    请问机器人到达终点的过程中最多有几次完全消耗完能量,消耗完这么多次能量的方式有几种。
     
    Sample Input
    1 6 6 4 5 6 6 4 3 2 2 3 1 7 2 1 1 4 6 2 7 5 8 4 3 9 5 7 6 6 2 1 5 3 1 1 3 7 2
     
    Sample Output
    3 4
     
    Author
    xhd
     
    Source
     
    Recommend
    lcy
     
    AC CODE
    #include <stdio.h>
    #include <queue>
    #include <string.h>
    #include <iostream>
    using namespace std;
    #define N 110
    
    typedef unsigned __int64 LL;
    
    struct node
    {
        LL x,y;
    };
    
    int n,m;
    LL g[N][N];
    LL mark[N][N];
    LL num[N][N];
    LL sum[N][N];
    
    
    void bfs()// 最后发现用bfs漏洞很多. 同时也说明有些用dp很容易解决的问题用搜索做也会变得比较复杂.
    { // 因为这题的状态转移很是纠结. 涉及到了加和. 用dfs 就会出现很多重复的. 从而导致加和的时候出现了问题.
        // 而用dp的话,简单好写而且很准确。  所以以后遇到这种满足dp性质的。 尽量选择dp解. 实在不行在用搜索.
        int a=0,b=1;
        LL mx=0;
        LL mxcnt=0;
        memset(num,0,sizeof(num));
        memset(mark,0,sizeof(mark));
        memset(sum,0,sizeof(sum));
        //queue<node> que[2];
        node tmp;
        tmp.x=1; tmp.y=1; 
       // que[0].push(tmp);
        
        num[1][1]=1; // 用来记录达到这个次数有多少种方法
        mark[1][1]=1;// 用来标记
        sum[1][1]=0; // 用来记录次数
        node cur;
        for(cur.x=1;cur.x<=n;cur.x++)
            for(cur.y=1;cur.y<=m;cur.y++) // 想了想还是不好弄的.
            {
            //    node cur=que[b].front();
             //   que[b].pop();
              //  mark[cur.x][cur.y]=0; // 表示这个位置已经取出
                int k=g[cur.x][cur.y];
                if(cur.x==n&&cur.y==m) continue;
                if(num[cur.x][cur.y]==0) continue;
                if(k==0) continue;
    
                if(n-cur.x+m-cur.y<=k)
                {
                    LL tnum = sum[cur.x][cur.y];
                    if( n-cur.x+m-cur.y==k )
                    {
                        tnum++;
                    }
                        if( tnum > mx)
                        {
                            mx = tnum;
                            mxcnt=num[cur.x][cur.y];
                        }
                        else if(tnum==mx) mxcnt += num[cur.x][cur.y];
                    continue;
                }
                
                for(int i=0;i<=k;i++)
                {
                    int cx=cur.x+i; int cy=cur.y+k-i;
                    if( (cx>=1&&cx<=n)&&(cy>=1&&cy<=m) && g[cx][cy]!=0 )
                    {
                        node nwnode;
                        nwnode.x=cx; nwnode.y=cy;
                        if( sum[cur.x][cur.y]+1 >= sum[cx][cy] )
                        {
                            if( sum[cur.x][cur.y]+1 == sum[cx][cy] )
                            {
                                num[cx][cy] += num[cur.x][cur.y];
                            }
                            else
                            {
                                sum[cx][cy] = sum[cur.x][cur.y]+1;
                                num[cx][cy] = num[cur.x][cur.y];
                            }
                           /* if( mark[cx][cy]==0 )
                            {
                                mark[cx][cy]=1;
                                que[a].push(nwnode);
                            }*/
                        }
                    }
                }
            }
        printf("%I64d %I64d\n",mx,mxcnt);
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
             for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    scanf("%I64d",&g[i][j]);
            bfs();
        }
        return 0;
    }
    BFS 不能ac的
    #include <stdio.h>
    #include <queue>
    #include <string.h>
    #include <iostream>
    using namespace std;
    #define N 110
    
    typedef __int64 LL;
    
    struct node
    {
        int x,y;
    };
    
    int n,m;
    int g[N][N];
    int mark[N][N];
    LL num[N][N];
    LL sum[N][N];
    
    
    void bfs()
    {
        int a=0,b=1;
        LL mx=0;
        LL mxcnt=0;
        memset(num,0,sizeof(num));
        memset(mark,0,sizeof(mark));
        memset(sum,0,sizeof(sum));
        queue<node> que[2];
        while(que[0].size()!=0) que[0].pop();
        while(que[1].size()!=0) que[1].pop();
        node tmp;
        tmp.x=1; tmp.y=1; 
        que[0].push(tmp);
        
        num[1][1]=1; // 用来记录达到这个次数有多少种方法
        mark[1][1]=1;// 用来标记
        sum[1][1]=0; // 用来记录次数
        while(que[a].size()!=0)
        {
            swap(a,b);
            while(que[b].size()!=0)
            {
                node cur=que[b].front();
                que[b].pop();
                mark[cur.x][cur.y]=0; // 表示这个位置已经取出
                int k=g[cur.x][cur.y];
                
                for(int i=0;i<=k;i++)
                {
                    int cx=cur.x+i; int cy=cur.y+k-i;
                    if( (cx>=1&&cx<=n)&&(cy>=1&&cy<=m) && g[cx][cy]!=0 )
                    {
                        node nwnode;
                        nwnode.x=cx; nwnode.y=cy;
                        if( sum[cur.x][cur.y]+1 >= sum[cx][cy] )
                        {
                            if( sum[cur.x][cur.y]+1 == sum[cx][cy] )
                            {
                                num[cx][cy] += num[cur.x][cur.y]; // num 那里有问题.
                            }
                            else
                            {
                                sum[cx][cy] = sum[cur.x][cur.y]+1;
                                num[cx][cy] = num[cur.x][cur.y];
                            }
                            if( mark[cx][cy]==0 )
                            {
                                mark[cx][cy]=1;
                                que[a].push(nwnode);
                            }                                                   
                        }
                    }
                }
            }
        }
        for(int i=1 ; i<=n ; i++)
            for(int j=1 ; j<=m ; j++)
            {
                if(num[i][j]==0)  continue;
                if(i==n&&j==m) continue;
                int k=g[i][j];
                if(n-i+m-j<=k)
                {
                    int tnum = sum[i][j];
                    if( n-i+m-j==k ) tnum++;
                        if( tnum > mx )
                        {
                            mx = tnum;
                            mxcnt=num[i][j];
                        }
                        else if(tnum==mx) mxcnt += num[i][j];
                    continue;
                }
            }
        printf("%I64d %I64d\n",mx,mxcnt); 
        //bfs1();
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
             for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    scanf("%d",&g[i][j]);
            bfs();
        }
        return 0;
    }
  • 相关阅读:
    【NOIP2001】【Luogu1025】数的划分(可行性剪枝,上下界剪枝)
    【POJ2676】Sudoku(优化搜索顺序)
    【codevs4228】小猫爬山(最优化剪枝)
    实现两个路由器漫游(传统路由器做AP)
    查询数据SELECT 之单表查询
    MySQL数据库基础概念
    删除Mac上的mysql数据库
    MYSQL数据库
    并发编程
    socketserver及相关的类 (处理socket服务端)+ event事件的使用
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/2934246.html
Copyright © 2011-2022 走看看