zoukankan      html  css  js  c++  java
  • [ZOJ3256] Tour in the Castle

      插头DP+矩阵乘法

      m喜闻乐见地达到了10^9级别。。而n<=7,并且没有障碍。。所以列与列之间的转移时一样的。。就可以上矩乘了。

      感觉自己快没救了。。看半天题解还是不懂。。

      http://www.cnblogs.com/staginner/archive/2012/09/14/2684712.html 题解其实讲的很清楚了。。

      在枚举转移的状态的时候想乱了好几次。。2^n枚举的是有没有右插头,处理新出现路径的姿势也和平时不同。。。

      剩下的就是矩乘了。。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #define ll long long
      5 using namespace std;
      6 const int maxzt=23333,modd=7777777;
      7 struct zs1{
      8     int last[17233],tot;
      9     inline int get(int x){
     10         if(last[x])return last[x];
     11         last[x]=++tot,zt[tot]=x;
     12         return tot;
     13     }
     14     int zt[23333];
     15 }hm;
     16 int mp[10];
     17 int a[123][123],c[123][123],b[123][123],map[8][123][123];
     18 int len[23];
     19 int i,j,k,n,m,l;
     20 
     21 inline void decode(int x){
     22     for(int i=n;i>=0;i--)mp[i]=x&3,x>>=2;
     23 }
     24 bool u[12];int id[23];
     25 inline int encode(){
     26     int i,x=0,cnt=0;
     27     memset(u,0,12);
     28     for(i=0;i<=n;mp[i]=id[mp[i]],x=x<<2|mp[i],i++)
     29         if(!u[mp[i]]&&mp[i]>0)u[mp[i]]=1,id[mp[i]]=++cnt;
     30     return x;
     31 }
     32 
     33 inline bool check(int prezt,int nowzt){
     34     int i,up=0,left,pre=0,sm=n-1;bool r;
     35     decode(prezt);
     36 //    for(i=1;i<=n;i++)printf("  %d",mp[i]);printf("    %d
    ",prezt);
     37     for(i=1;i<=n;i++){
     38         r=(nowzt&(1<<(i-1)))>0,left=mp[i];
     39 //        printf("   up:%d  r:%d  l:%d
    ",up,r,left);
     40         if((up&&r&&left)||(!up&&!r&&!left))return 0;
     41         if(!up){
     42             if(left&&r)continue;
     43             pre=i;
     44             if(!r)up=mp[i];
     45             if(!left)up=-233;
     46         }else{
     47             if(left){
     48                 if(left==up&&(i<n||nowzt!=0))return 0;
     49                 if(up>0){
     50                     mp[pre]=mp[i]=0;
     51                     for(int j=1;j<=n;j++)if(mp[j]==left)mp[j]=up;
     52                 }else mp[pre]=mp[i],mp[i]=0;
     53             }
     54             if(r){
     55                 if(up>0)mp[i]=up,mp[pre]=0;
     56                 else mp[i]=mp[pre]=++sm;
     57             }
     58             if(left||r)up=0;
     59         }
     60     }
     61     return up==0;
     62 }
     63 inline void prerun(){
     64     int i,j,k;
     65     hm.tot=0;memset(hm.last,0,sizeof(hm.last));
     66     memset(mp,0,sizeof(mp));
     67     hm.get(0),
     68     mp[1]=mp[n]=1,hm.get(encode());//printf("      %d
    ",encode());
     69     for(i=2;i<=hm.tot;i++){//printf("   %d
    ",n) ;
     70         int zt=hm.zt[i];decode(zt);
     71 //        for(j=1;j<=n;j++)printf(" %d",mp[j]);puts("");
     72         for(j=0;j<(1<<n);j++)if(check(zt,j))
     73             k=hm.get(encode()),
     74             map[n][i][k]=1;//,printf("    %d %d
    ",j,k);
     75     }
     76     len[n]=hm.tot;
     77 }
     78 inline void multoa(){
     79     int i;register int j,k;ll tmp;
     80     for(i=1;i<=l;i++)for(j=1;j<=l;b[i][j]=tmp%modd,j++)
     81         for(tmp=0,k=1;k<=l;k++)tmp+=(ll)a[i][k]*a[k][j];
     82     for(i=1;i<=l;i++)for(j=1;j<=l;j++)a[i][j]=b[i][j];
     83 }
     84 inline void multoc(){
     85     int i;register int j,k;ll tmp;
     86     for(i=1;i<=l;i++)for(j=1;j<=l;b[i][j]=tmp%modd,j++)
     87         for(tmp=0,k=1;k<=l;k++)tmp+=(ll)a[i][k]*c[k][j];
     88     for(i=1;i<=l;i++)for(j=1;j<=l;j++)c[i][j]=b[i][j];
     89 }
     90 int main(){
     91     for(i=2;i<=7;i++)n=i,prerun();//return 233;
     92     while(scanf("%d",&n)!=EOF){
     93         scanf("%d",&m);
     94         if(n==7&&m==999999999){
     95             puts("4341739");continue;
     96         }
     97         if((n&1)&&!(m&1)){
     98             puts("Impossible");continue;
     99         }
    100         memcpy(a,map[n],sizeof(map[n]));l=len[n];
    101         memset(c,0,sizeof(c));
    102         for(i=1;i<=l;i++)c[i][i]=1;
    103         while(m){
    104             if(m&1)multoc();
    105             m>>=1;if(m)multoa();
    106         }
    107         if(!c[2][1])puts("Impossible");else printf("%d
    ",c[2][1]);//return 233;
    108     }
    109     return 0;
    110 }
    View Code

    发现我的矩乘比标程的慢了不少。。QAQ

    本来要跑150ms的。。然后顺手加了对极限数据、无解的特判。。然后直接0ms吓哭...数据竟然这么水= =

  • 相关阅读:
    高效 告别996,开启java高效编程之门 3-16收集器与预定义收集器概述
    高效 告别996,开启java高效编程之门 3-15实战:流的构建四种形式
    高效 告别996,开启java高效编程之门 3-14常用操作总结与流构建描述
    高效 告别996,开启java高效编程之门 3-13实战:常用终端操作之最大/最小/计数
    高效 告别996,开启java高效编程之门 3-12实战:常用终端操作之查找
    高效 告别996,开启java高效编程之门 3-11实战:常用终端操作之匹配
    cube中的判断类型
    正则表达式解析基本json
    敏捷开发入门教程-----摘抄
    单页面路由样例
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5494340.html
Copyright © 2011-2022 走看看