zoukankan      html  css  js  c++  java
  • hdu3377之简单路径求最值

    Plan

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


    Problem Description
    One day, Resty comes to an incredible world to seek Eve -- The origin of life. Lilith, the sister of Eve, comes with him. Although Resty wants to find Eve as soon as possible, Lilith likes to play games so much that you can't make her make any move if you don't play with her.

    Now they comes to the magical world and Lilish ask Resty to play with her.

    The game is following :
    Now the world is divided into a m * n grids by Lilith, and Lilith gives each grid a score.
    So we can use a matrix to describe it.
    You should come from cell(0, 0) to cell(m-1, n-1) (Up-Left to Down-Right) and try to colloct as more score as possible.
    According to Lilish's rule, you can't arrive at each cell more than once.

    Resty knows that Lilish will be easy to find the max score, and he doesn't want to lose the game.
    So he want to find the game plan to reach the max score.

    Your task is to calculate the max score that Lilish will find, the map is so small so it shouldn't be difficult for you, right?
     

    Input
    The input consists of more than one testdata.
    Process to the END OF DATA.
    For each test data :
    the first live give m and n. (1<=m<=8, 1<=n<=9)
    following m lines, each contain n number to give you the m*n matrix.
    each number in the matrix is between -2000 and 2000
     

    Output
    Output Format is "Case ID: ANS" one line for each data
    Don't print any empty line to the output
     

    Sample Input
    2 2 1 2 3 1 3 3 0 -20 100 1 -20 -20 1 1 1
     

    Sample Output
    Case 1: 5 Case 2: 61
    分析:

    首先初始化状态即[1,0]的状态为1,表示从[1,0] => [1,1]有一个插头,这样就能保证是从点[1,1]開始
    然后将点[n+1,m]表示为可经过。然后进行插头DP时从[n,m] => [n+1,m]能够有插头。所以终于也保证了以点[n,m]结束
    在这个过程中进行插头DP仅仅须要去掉p=1,q=2的情况即可,由于这样会形成环
    
    另外另一种方法是添加外围使得题目变成求回路的最值
    0 0 0 0 0
    0 # # # 0
    ------
    1 0 1 |# 0
    1 1 1 |# 0
    ------
    # # 0 0 0
    这样添加外围就一定能保证求的回路是假设去掉外围就是从点[1,1]到[n,m]
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <algorithm>
    #include <map>
    #include <cmath>
    #include <iomanip>
    #define INF 99999999
    typedef long long LL;
    using namespace std;
    
    const int MAX=30000+10;
    const int N=10+10;
    int n,m,size,index;
    int val[N][N],total[2],bit[N];
    int head[MAX],next[MAX],Hash[MAX];
    LL dp[2][MAX],state[2][MAX],sum;
    
    void HashCalState(LL s,LL Val){
        int pos=s%MAX;
        for(int i=head[pos];i != -1;i=next[i]){
            if(state[index][Hash[i]] == s){
                dp[index][Hash[i]]=max(dp[index][Hash[i]],Val);
                return;
            }
        }
        ++total[index];
        state[index][total[index]]=s;
        dp[index][total[index]]=Val;
        //头插法 
        Hash[size]=total[index];
        next[size]=head[pos];
        head[pos]=size++; 
    }
    
    void DP(){
        index=0;
        total[index]=1;
        state[index][1]=1;//初始化的状态是第一格有一个插头进来(从0进来) 
        dp[index][1]=val[1][1];
        sum=-INF;
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                memset(head,-1,sizeof head);
                size=0;
                index=index^1;
                total[index]=0;
                for(int k=1;k<=total[index^1];++k){
                    LL s=state[index^1][k];
                    LL Val=dp[index^1][k];
                    int p=(s>>bit[j-1])%4;
                    int q=(s>>bit[j])%4;
                    int d=(s>>bit[j+1])%4;
                    if(!p && !q){
                        HashCalState(s,Val);//跳过该格不经过(这里能够不用加推断if(i != n || j != m),由于n-1,m一定会经过n,m) 
                        if(val[i][j+1] == INF || val[i+1][j] == INF)continue;
                        s=s+(1<<bit[j-1])+2*(1<<bit[j]);
                        if(!d)HashCalState(s,Val+val[i+1][j]+val[i][j+1]+val[i][j]);//注意这里一定还要加上val[i][j]  
    					else HashCalState(s,Val+val[i+1][j]+val[i][j]);//假设i,j+1已经由上面一行到达则不能反复累加该点价值 
                    }else if(!p && q){
                        if(val[i][j+1] != INF){
                        	//if(!d)Val=Val+val[i][j+1];//这里不能这样改变Val,由于会影响下一个if里面的Val
                        	if(!d)HashCalState(s,Val+val[i][j+1]); 
                       	 	else HashCalState(s,Val);//假设i,j+1已经由上面一行到达则不能反复累加该点价值
                        }
                        if(val[i+1][j] != INF){
                            s=s+q*(1<<bit[j-1])-q*(1<<bit[j]);
                            Val=Val+val[i+1][j];
                            HashCalState(s,Val);
                        }
                    }else if(p && !q){
                        if(val[i+1][j] != INF)HashCalState(s,Val+val[i+1][j]);
                        if(val[i][j+1] != INF){
                            s=s-p*(1<<bit[j-1])+p*(1<<bit[j]);
                            if(!d)HashCalState(s,Val+val[i][j+1]);
                            else HashCalState(s,Val);//假设i,j+1已经由上面一行到达则不能反复累加该点价值
                        }
                    }else if(p == 1 && q == 1){
                        int b=1;
                        for(int t=j+1;t<=m;++t){
                            int v=(s>>bit[t])%4;
                            if(v == 1)++b;
                            if(v == 2)--b;
                            if(!b){
                                s=s+(1<<bit[t])-2*(1<<bit[t]);
                                break;
                            }
                        }
                        s=s-(1<<bit[j-1])-(1<<bit[j]);
                        HashCalState(s,Val);
                    }else if(p == 2 && q == 2){
                        int b=1;
                        for(int t=j-2;t>=0;--t){
                            int v=(s>>bit[t])%4;
                            if(v == 2)++b;
                            if(v == 1)--b;
                            if(!b){
                                s=s-(1<<bit[t])+2*(1<<bit[t]);
                                break;
                            }
                        }
                        s=s-2*(1<<bit[j-1])-2*(1<<bit[j]);
                        HashCalState(s,Val);
                    }else if(p == 2 && q == 1){
                        s=s-2*(1<<bit[j-1])-(1<<bit[j]);
                        HashCalState(s,Val);
                    }
                }
            }
            for(int k=1;k<=total[index];++k)state[index][k]<<=2;
        }
        sum=dp[index][1];//for(int k=1;k<=total[index];++k)sum=max(sum,dp[index][k]);//这里能够不用for,由于最后到达n,m->n+1,m状态仅仅有一种 
    }
    
    int main(){
        int num=0;
        for(int i=0;i<N;++i)bit[i]=i<<1;
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<N;++i)for(int j=1;j<N;++j)val[i][j]=INF;//这里i<=N,j<=N会覆盖bit的内存地址,教训啊 
            for(int i=1;i<=n;++i){
                for(int j=1;j<=m;++j)scanf("%d",&val[i][j]);
            }
            val[n+1][m]=0;//在最后一个以下加入一个虚拟格子能够经过,则插头dp后的路线一定是以最后一格结尾 
            DP();
            printf("Case %d: %lld
    ",++num,sum);
        }
        return 0;
    }
    /*
    7 8
    1  1  1  1  1  1  1  1
    -1 -1 -1 -1 -1 -1 -1  1
     1  1  1 -1 -1 -1 -1  1
     1 -1  1 -1 -1 -1 -1  1
     1 -1  1  1  1  1  1  1
     1 -1 -1 -1 -1 -1 -1 -1
     1  1  1  1  1  1  1  1
    */


  • 相关阅读:
    上下文有关文法
    sqlserver cte 速度慢
    hibernate tools eclipse 安装
    sts java nullpointer exception
    Oracle RAC集群体系结构
    bean scope scoped-proxy
    hibernate persist不能插入到表中
    system.out 汉字乱码
    NoSQL数据库(转)
    在PowerShell中获取本地的RAM信息(容量)
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7045262.html
Copyright © 2011-2022 走看看