zoukankan      html  css  js  c++  java
  • 51nod1683

    代码参考:http://blog.csdn.net/sdfzyhx/article/details/74359927

    //dp[i][j][k]表示到了第i列,最下边的点最短路为j,剩下的点之间的关系为k的方案; 
    //只需知道这一行的棋盘状态和上一行的最短路之间的相对关系(1,0,-1)即可完成转移; 
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int max4=1050,max2=70,maxm=110,maxn=10;
    int transx[max4][max2],transy[max4][max2],dp[2][maxm][max4],last[2][maxm][max4];
    int ans[maxm],f[maxn],tem[maxn],dis[maxn],quex[2][300000],quey[2][300000],n,m,p;
    void update(int &x,int y){
        x+=y;
        x=(x>=p?x-p:x);
    }
    int main(){
        int x,y,x1,y1,ok,tl[2];
        scanf("%d%d%d",&n,&m,&p);
        //预处理转移数组; 
        for(int s=0;s<(1<<(2*(n-1)));++s){//上一行的最短路情况; 
            ok=1;
            for(int i=1;i<n;++i){
                x=(s>>((i-1)*2))&3;
                if(x==2){ok=0;break;}
                if(x){
                    if(x==1)f[i]=f[i-1]+1;
                    else f[i]=f[i-1]-1;
                }
                else f[i]=f[i-1];
            }
            if(!ok)continue;
            for(int t=0;t<(1<<n);++t){//这一行的棋盘情况; 
                for(int i=0;i<n;++i)tem[i]=(t>>i)&1;
                dis[0]=f[0]+tem[0];
                for(int i=1;i<n;++i)dis[i]=min(dis[i-1],f[i])+tem[i];
                for(int i=n-2;i>=0;--i)dis[i]=min(dis[i],dis[i+1]+tem[i]);
                transy[s][t]=dis[0];
                for(int i=1;i<n;++i){
                    if(dis[i]==dis[i-1])x=0;
                    else if(dis[i]==dis[i-1]+1)x=1;
                    else x=3;
                    transx[s][t]|=x<<(2*(i-1)); 
                }
            }
        }
        //处理初始态;
        for(int t=0;t<(1<<n);++t){
            x=0;
            for(int i=1;i<n;++i)if((t>>i)&1)x|=1<<(2*(i-1));
            y=t&1;
            if(last[1][y][x])update(dp[1][y][x],1);
            else{
                last[1][y][x]=1;
                dp[1][y][x]=1;
                tl[1]++;
                quex[1][tl[1]]=x;
                quey[1][tl[1]]=y;
            } 
        }
        //转移
        for(int i=2,c=0;i<=m;++i,c^=1){
            tl[c]=0;
            for(int j=1;j<=tl[c^1];++j){
                x=quex[c^1][j];
                y=quey[c^1][j];
                for(int t=0;t<(1<<n);++t){
                    x1=transx[x][t];
                    y1=y+transy[x][t];
                    if(last[c][y1][x1]==i)update(dp[c][y1][x1],dp[c^1][y][x]);
                    else{
                        last[c][y1][x1]=i;
                        dp[c][y1][x1]=dp[c^1][y][x];
                        tl[c]++;
                        quex[c][tl[c]]=x1;
                        quey[c][tl[c]]=y1;
                    }
                }
            } 
        }
        //统计答案
        for(int j=1;j<=tl[m&1];++j){
            x=quex[m&1][j];
            y1=y=quey[m&1][j];
            for(int i=1;i<n;++i){
                x1=(x>>(2*(i-1)))&3;
                if(x1==1)y1++;
                else if(x1==3)y1--;
            }
            update(ans[y1],dp[m&1][y][x]);
        } 
        for(int i=0;i<n+m;++i)printf("%d
    ",ans[i]);
        return 0;
    } 
  • 相关阅读:
    包含min函数的栈
    栈的应用
    给定金额m和红包数量n
    顺时针打印矩阵
    二叉树的镜像
    elementUI table表头错位问题
    金额格式化
    ajax跨域问题全解
    JavaScript 的 this 原理
    vue技术分享-你可能不知道的7个秘密
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/8505866.html
Copyright © 2011-2022 走看看