zoukankan      html  css  js  c++  java
  • 【POJ】3133 Manhattan Wiring

    【算法】插头DP

    【题解】蓝书原题 

    动态规划

    [原创]插头DP小结(ACM by kuangbin)

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int MAXD=15;
    const int MOD=10007;
    const int STATE=500010;
    int n,m;
    int map[MAXD][MAXD];
    int code[MAXD];
    struct HASHMAP{
        int first[MOD],tot,from[STATE],state[STATE],f[STATE];
        void init()//清空 
        {
            tot=0;
            memset(first,0,sizeof(first));
        }
        void push(int number,int num)//插入 
        {
            int x=number%MOD;
            for(int i=first[x];i;i=from[i])
             if(number==state[i])
              {
                  f[i]=min(f[i],num);
                  return;//已有,不用加入,直接return 
              }
            tot++;
            state[tot]=number;
            f[tot]=num;
            from[tot]=first[x];
            first[x]=tot;
        }
    }hm[2];
    
    void decode(int st)//解码
    {
        for(int i=m;i>=0;i--)//数组第m位是最右边 
         {
             code[i]=(st&3);//'&'取出1 
             st>>=2;
         }
    }
    int encode()//四进制,0无插头 2、3插头 
    {
        int st=0;
        for(int i=0;i<=m;i++)
         {
             st<<=2;
             st|=code[i];
         }
        return st;
    }
    void shift()//指向右边界的插头不存在,空出了一位,全体右移一位,把最左插头空出来 
    {
        for(int i=m;i>0;i--)code[i]=code[i-1];
        code[0]=0;
    }
    void dpblank(int i,int j,int cur)//空格map[i][j]=1 
    {
        int left,up;
        for(int k=1;k<=hm[cur].tot;k++)
         {
             decode(hm[cur].state[k]);
             left=code[j-1];//左在本体,本来是j,但因为从0开始编号…… 
             up=code[j];
             if(left&&up)
              {
                  if(left==up)//只接受相同插头 
                   {
                       code[j-1]=code[j]=0;//设置 
                       if(j==m)shift();//过行 
                       hm[cur^1].push(encode(),hm[cur].f[k]+1);//入队 
                   }
              }
             else if((left&&(!up))||(!left)&&up)
              {
                  int t;
                  if(left)t=left;else t=up;//从左或从上 
                  if(map[i][j+1]==1||map[i][j+1]==t)//往右
                  {
                      code[j-1]=0;code[j]=t;
                      hm[cur^1].push(encode(),hm[cur].f[k]+1);
                  }
                if(map[i+1][j]==1||map[i+1][j]==t)//往下
                 {
                     code[j-1]=t;code[j]=0;
                     if(j==m)shift(); 
                     hm[cur^1].push(encode(),hm[cur].f[k]+1);
                 } 
              }
             else
              {
                  code[j-1]=code[j]=0;//留空 
                  if(j==m)shift();
                  hm[cur^1].push(encode(),hm[cur].f[k]);
                  if(map[i][j+1]&&map[i+1][j])//开左下插头 
                   {
                       int r=map[i][j+1],d=map[i+1][j];
                       if(r==1&&(d==1||d==2)||r==2&&(d==1||d==2))
                        {
                            decode(hm[cur].state[k]);//刚可能换行破坏了,重新解码(挺快的) 
                            code[j-1]=code[j]=2;
                            hm[cur^1].push(encode(),hm[cur].f[k]+1);
                        }
                       if(r==1&&(d==1||d==3)||r==3&&(d==1||d==3))
                        {
                            decode(hm[cur].state[k]);
                            code[j-1]=code[j]=3;
                            hm[cur^1].push(encode(),hm[cur].f[k]+1);
                        }
                   }
              }
         }
    }
    void dpblock(int i,int j,int cur)
    {
        for(int k=1;k<=hm[cur].tot;k++)
         {
             decode(hm[cur].state[k]);
            code[j-1]=code[j]=0;
            if(j==m)shift();
            hm[cur^1].push(encode(),hm[cur].f[k]);
         }
    }
    void dp_begin(int i,int j,int cur,int x)//只接受一个插头(凭空消失)或只从一边出去(凭空出现) 
    {
        int left,up;
        for(int k=1;k<=hm[cur].tot;k++)
         {
             decode(hm[cur].state[k]);
             left=code[j-1];up=code[j];
             if(left+up==x)
              {
                  code[j-1]=code[j]=0;
                  if(j==m)shift();
                  hm[cur^1].push(encode(),hm[cur].f[k]+1);//半条边最后再减掉,避免浮点数运算 
              }
             if(left+up==0)
              {
                  if(map[i][j+1]==1||map[i][j+1]==x)
                   {
                       code[j-1]=0;code[j]=x;
                       hm[cur^1].push(encode(),hm[cur].f[k]+1);
                   }
                  if(map[i+1][j]==1||map[i+1][j]==x)
                   {
                       code[j-1]=x;code[j]=0;
                       if(j==m)shift();
                       hm[cur^1].push(encode(),hm[cur].f[k]+1);
                   }
              }
         }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        while(n!=0||m!=0)
         {
             memset(map,0,sizeof(map));
             for(int i=1;i<=n;i++)
              for(int j=1;j<=m;j++)
               {
                   int u;
                   scanf("%d",&u);
                   if(u==0)map[i][j]=1;
                   if(u==1)map[i][j]=0;
                   if(u>1)map[i][j]=u;
               }
            int cur=0;hm[0].init();hm[0].push(0,0);
            for(int i=1;i<=n;i++)
             for(int j=1;j<=m;j++)
              {
                  hm[cur^1].init();//根据上一格状态板刷这一格
                if(map[i][j]==0)dpblock(i,j,cur);
                 else if(map[i][j]==1)dpblank(i,j,cur);
                 else if(map[i][j]==2)dp_begin(i,j,cur,2);
                 else if(map[i][j]==3)dp_begin(i,j,cur,3);
                cur^=1; 
              }
            int ans=0;
            for(int i=1;i<=hm[cur].tot;i++)
             ans+=hm[cur].f[i];
            if(ans>0)ans-=2;
            printf("%d
    ",ans);
             scanf("%d%d",&n,&m);
         }
    }
    View Code
  • 相关阅读:
    第十三课:js操作节点的创建
    matlab 绘制条形图
    Pearson(皮尔逊)相关系数及MATLAB实现
    Spearman Rank(斯皮尔曼等级)相关系数及MATLAB实现
    A Regularized Competition Model for Question Diffi culty Estimation in Community Question Answering Services-20160520
    Competition-based User Expertise Score Estimation-20160520
    We Know What @You #Tag: Does the Dual Role Affect Hashtag Adoption-20160520
    matlab 画图数据导入
    Who Says What to Whom on Twitter-www2011-20160512
    The Lifecycle and Cascade of WeChat Social Messaging Groups-www2016-20160512
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6745150.html
Copyright © 2011-2022 走看看