zoukankan      html  css  js  c++  java
  • 【XSY1552】自动机 构造

    题目大意

      给你一个自动机,包含(n)个状态,指令集为前(m)个小写字母,对于每个状态(s)和每个指令(i),自动机均有后继(T(s,i))。请你求出一个长度不超过(2^{20})的指令序列,使得无论自动机当前处在哪个状态(包括初始状态),按顺序执行指令序列的所有指令后,自动机都处于初始状态(1)。无解输出([impossible])

      (1leq nleq 100,1leq mleq 26)

    题解

      首先要证明一个结论:原问题有解等价于对于任意状态(i),都存在一个指令序列(S_i)使得(T(s,S_i)=1)(T(1,S_i)=1)

      必要性显然。如果不存在(S_i),那么状态(i)和状态(1)一定不可能同时转移到状态(1)

      对于充分性,我们考虑所有当前可能的状态集合(U)。一开始(U={1,2,3ldots n})。每次我们任选(U)中一个状态(t),执行(S_t)。这样我们会得到一个集合(U'),满足(1in U')(|U'|<|U|)。这样我们经过若干步后可以得到(U={1})。我们把所有(S_t)连在一起得到一个指令序列(S),易证(S)是满足要求的。

      所以我们每次任选(U)中的一个状态(t),求出(S_t),然后执行(S_t),直到(|U|=1)为止。

      对于状态(i),求(S_i)的时间复杂度是(O(n^2))的,执行(S_i)(O(n^3))的,总共要执行(O(n))次,所以时间复杂度是(O(n^4))的。

      每个(S_i)的长度是(O(n^2))的,总共要执行(O(n))次,所以答案的长度是(O(n^3))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    int a[110][30];
    int n,m;
    char s[10000010];
    int cnt;
    int c[110];
    int d[110];
    int vis[110][110];
    int st[10010];
    int top;
    int dfs(int x,int y)
    {
    	if(x==1&&y==1)
    		return 1;
    	vis[x][y]=1;
    	int i;
    	for(i=1;i<=m;i++)
    	{
    		int lx=a[x][i];
    		int ly=a[y][i];
    		if(!vis[lx][ly])
    		{
    			st[++top]=i;
    			if(dfs(lx,ly))
    				return 1;
    			top--;
    		}
    	}
    	return 0;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int i,j;
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    		{
    			scanf("%d",&a[i][j]);
    			a[i][j]++;
    		}
    	cnt=0;
    	for(i=1;i<=n;i++)
    		c[i]=i;
    	int now=n;
    	while(now>1)
    	{
    		memset(vis,0,sizeof vis);
    		top=0;
    		if(!dfs(1,c[2]))
    		{
    			printf("[impossible]");
    			return 0;
    		}
    		for(i=1;i<=top;i++)
    		{
    			s[++cnt]=st[i]+'a'-1;
    			for(j=1;j<=now;j++)
    				c[j]=a[c[j]][st[i]];
    		}
    		sort(c+1,c+now+1);
    		now=unique(c+1,c+now+1)-c-1;
    	}
    	s[cnt+1]='';
    	printf("%s
    ",s+1);
    	return 0;
    }
    
  • 相关阅读:
    不要随便用#define 沉沉_
    转载堆和栈的区别 沉沉_
    转载include包含源文件引发的错误 沉沉_
    浅议C和C++中的内存分配 沉沉_
    volatile 的应用 沉沉_
    Debian显示txt乱码
    Debian 64位安装wink
    Debian安装vmware虚拟机
    Debian安装scim中文、日语输入法
    Debian安装chrome
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8510708.html
Copyright © 2011-2022 走看看