zoukankan      html  css  js  c++  java
  • 【2016北京集训测试赛(七)】自动机 (思考题)

     

    Time Limit: 1000 ms Memory Limit: 256 MB

    Description

      


    Solution

      这是一道看起来令人毫无头绪的题,然而确实十分简单巧妙TAT。

      题目要求所有点执行相同指令后都回到初始状态。

      我们先来考虑只有两种状态的情况:初始状态$T_0$与另一个状态$T_x$。

      这样,我们可以通过一个二元记忆化深搜,来得到一种方案A,使得$T_0$回到$T_0$,且$T_x$回到$T_0$。如果这个方案都不存在,那么此时无解。

      现在我们知道,执行方案A后,$T_x$与$T_0$合并为一个$T_0$了!那么我们对全局都执行方案A,可以发现至少会有包括$T_x$在内的若干个状态被合并为$T_0$。

      因此在$O(n)$的次数里,我们可以按照下列步骤逐个合并状态:

      1. 对$T_0$与任意一个状态$T_x$进行深搜,得到一个方案。如果方案不存在,则无解。
      2. 对全局模拟此方案,合并相同的节点,回到1.直到只剩下$T_0$

      答案是?所有方案连在一起输出就好啦。


     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N=101;
     4 int n,m,ch[N][26];
     5 int size,lis[2000010],st[2000010],top,ans[2000010],len;
     6 int vis[N][N];
     7 bool dfs(int x,int y){
     8     if(x==0&&y==0) return true;
     9     if(vis[x][y]) return false;
    10     vis[x][y]=1;
    11     for(int i=0;i<m;i++){
    12         st[++top]=i;
    13         if(dfs(ch[x][i],ch[y][i])) return true;
    14         st[top--]=0;
    15     }
    16     return false;
    17 }
    18 int main(){
    19     scanf("%d%d",&n,&m);
    20     for(int i=0;i<n;i++)
    21         for(int j=0,x;j<m;j++)
    22             scanf("%d",&x),
    23             ch[i][j]=x;
    24     for(int i=1;i<=n;i++) lis[i]=i-1;
    25     size=n;
    26     while(size>1){
    27         memset(vis,0,sizeof vis);
    28         top=0;
    29         if(!dfs(0,lis[2])){
    30             printf("[impossible]
    ");
    31             return 0;
    32         }
    33         for(int j=1;j<=top;j++){
    34             ans[len++]='a'+st[j];
    35             for(int i=1;i<=size;i++)
    36                 lis[i]=ch[lis[i]][st[j]];
    37         }
    38         sort(lis+1,lis+1+size);
    39         size=unique(lis+1,lis+1+size)-lis-1;
    40     }
    41     for(int i=0;i<len;i++) putchar(ans[i]);
    42 }
    神奇代码
  • 相关阅读:
    ASP.net 网站项目:Fckeditor使用StepByStep
    SQL2005触发器写法
    Android 中 PopupWindow使用
    storyboard学习笔记-1
    判断两矩形是否相交
    CListCtrl 使用
    字符串和数字之间的转换(Unicode)
    【转】全特化/偏特化
    判断点是否在多边形内——射线法
    c++强制转化
  • 原文地址:https://www.cnblogs.com/RogerDTZ/p/7388975.html
Copyright © 2011-2022 走看看