sgu-201 Non Absorbing DFA

题目大意:

给你一个字符串,表示拥有的字符为长度L,即操作的种类L ,然后给你一个无向图,有n个顶点,标号从1~n,之后输入一个S,表示起点,即你一开始所在的位置,然后给你一个集合Σ,先输入元素个数,然后输入包含的元素有哪些。然后再给你一个数N,表示操作的字符串长度。最后停留的点必须在Σ中。

之后输入一个n*L的矩阵,第i行第j列表示在点号为i的点上进行字符操作 j 将会到达的点,记为change[ i ][ j ]。

之后又是一个n*L的矩阵,第i行第j列表示在点号为i的点上进行字符操作 j 是否会消耗掉当前的字符 j ,如果是0,表示会消耗,跳到下一个字符,如果是1,表示不会消耗字符,在下一个点继续进行操作j。记为cost[ i ][ j ]

然后就是要得出有多少种操作字符串。

解题思路:

首先预处理。

首先对于点i的字符操作 j ,如果cost[ i ][ j ]=0,表示直接消耗掉,我们先不管。如果cost[ i ][ j ]=1,那么就需要查找到最后到消耗掉这个字符会到达哪里。但是有可能会出现最后无法消耗掉,那么我们就打一个标记,说明不能在 i 点进行 j 操作。

然后直接DP,f[ i ][ j ]表示消耗i个字母最后在点 j 停留的种类。

如果 j 可以  进行 p 操作,那么

f[ i+1 ][ change[ j ][ p ] ]+=f[i][j] (p=1->L)

最后输出所有 的f[ N ][ Σ[i] ]

要写高精度!!!!

AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#define MAX(a,b) ((a)>(b)?(a):(b))

using namespace std;
int len;//字符数
int U;//点数
int S;//起点
int xigema[1010]={0};
int sx=0;//Σ的包含数
int n;//答案的长度
struct bian_
{
	int change;
	int cost;
}bian[10010][30]={{{0,0}}};
int f[70][1010][50]={{{0}}};
int hash[1010]={0};
int Times=0;

void Add(int p,int q,int pp,int qq)
{
	f[p][q][0]=MAX(f[p][q][0],f[pp][qq][0]);
	for(int i=1;i<=f[p][q][0];i++)
	{
		f[p][q][i]+=f[pp][qq][i];
		f[p][q][i+1]+=f[p][q][i]/10000;
		f[p][q][i]%=10000;
	}
	for(int i=f[p][q][0];f[p][q][i+1]>0;i++,f[p][q][0]++)
	{
		f[p][q][i+1]+=f[p][q][i]/10000;
		f[p][q][i]%=10000;
	}
	return;
}

int dfs(int k,int p)
{
	if(hash[k]==Times)
		return -1;
	hash[k]=Times;
	if(bian[k][p].cost==0)
		return bian[k][p].change;
	else return dfs(bian[k][p].change,p);
}

int main()
{
	char ch[10010]="\0";
	gets(ch);
	len=strlen(ch);
	for(;ch[len-1]=='\n' || ch[len-1]=='\r';ch[--len]='\0');
	scanf("%d",&U);
	scanf("%d",&S);
	scanf("%d",&sx);
	for(int i=1;i<=sx;i++)
	{
		int j;
		scanf("%d",&j);
		xigema[j]=1;
	}
	for(int i=1;i<=U;i++)
		for(int j=1;j<=len;j++)
			scanf("%d",&bian[i][j].change);
	for(int i=1;i<=U;i++)
		for(int j=1;j<=len;j++)
			scanf("%d",&bian[i][j].cost);
	scanf("%d",&n);

	for(int i=1;i<=U;i++)
		for(int j=1;j<=len;j++)
			if(bian[i][j].cost==1)
			{
				Times++;
				bian[i][j].change=dfs(bian[i][j].change,j);
				if(bian[i][j].change!=-1)
					bian[i][j].cost=0;
			}
	f[0][S][0]=f[0][S][1]=1;

	for(int i=0;i<n;i++)
		for(int j=1;j<=U;j++)
			for(int p=1;p<=len;p++)
				if(bian[j][p].cost==0)
					Add(i+1,bian[j][p].change,i,j);

	for(int i=1;i<=U;i++)
		if(xigema[i]==1)
			Add(0,0,n,i);

	printf("%d",f[0][0][f[0][0][0]]);
	for(int i=f[0][0][0]-1;i>0;i--)
		printf("%04d",f[0][0][i]);
	return 0;
}
时间: 2024-10-23 03:38:12

sgu-201 Non Absorbing DFA的相关文章

201. Non Absorbing DFA

题意好难看懂的说... 有限状态自动机DFA是这么一个有序组<Σ, U, s, T, phi>:Σ代表输入字符集,表示此自动机的工作范围:U代表所有的状态集合:s是初始状态:T是最终状态:phi代表转移函数,定义为phi : U × Σ → U. 利用DFA进行字符串识别是要你做这么一件事情:The input of the automation is the string α over Σ. Initially the automation is in state s. Each step

CocoSourcesCS 3

1 /*---------------------------------------------------------------------- 2 Compiler Generator Coco/R, 3 Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz 4 extended by M. Loeberbauer & A. Woess, Univ. of Linz 5 with improvements b

AC自动机- 自我总结

AC自动机算法总结  No.1 What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一. 简单的说,KMP用来匹配一个模式串:但如果现在有多个模式串需要在同一篇文章中出现,现在就需要Aho-Corasick automaton算法了. 不要天真的以为AC自动机为auto-Accept,虽然他能让你AC一些题. No.2 My Understanding About Aho-Corasick automato

ASC(2)A(大数+图论DP)

Non Absorbing DFA Time Limit: 10000/5000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description In the theory of compilers and languages finite state machines, also known as finite automata are widel

利用子集构造法实现NFA到DFA的转换

概述 NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够比较方便的机械实现且识别能力方面也和NFA相当.本次实验采用子集构造法来实现不带空弧的由NFA到DFA的转换. 子集构造法的算法如下: 设NFA为M=(K,Σ,f,S0,Z),则构造相应的DFA  M′=(Q,Σ,f′,I0,F)①取I0=S0:②对于状态集Q中任一尚未标记的状态qi={Si1,Si

词法分析器--DFA(c++实现)

语言名为TINY 实例程序: begin var x,y:interger; x:=10; read(x); if y<0 then x:=x-y; x:=x+y; write(x); end TINY语言扫描程序的DFA: 代码 //ExplLexicalAnalyzer.h #ifndef EXPLLEXICALANALYZER_H #define EXPLLEXICALANALYZER_H #define MAXTOKENLEN 40 #define MAXRESERVED 13 type

SGU 101 题解

#include<iostream> #include<algorithm> using namespace std; struct sticktype { int l; int r; bool vis; }stick[101]; struct pointtype { int amount; int next[7]; bool vis; }point[7]; int tail=0; int queue[201]; void dfs(int p); int main() { int

SGU 116

简单DP,可以理解为背包问题的变式.(想当初苯渣会错题意,以为只要输出任意一组解啊!结果一趟DFS在第14个点上WA三次啊!TUT) (第14个点上WA的一定是用贪心或一趟DFS做的!) 首先找到10000以内的super_prime,共201个.(不是打表- -) 这部分代码可以在行到行找到. 然后DP:f[i]代表用最少SUPER_PRIME构成i的数目,prev[i]保存序列. f[i]=f[i-super[j]]+1(如果super[j]<=i,1<=j<=201) #inclu

azure云迁移后expdp报错ORA-01110: data file 201: &#39;/home/oradata/powerdes/temp01.dbf&#39;

1,expdp的时候报错: 在idc的oracle服务器上正常导入导出都ok的,但是到了azure云上就出故障了: [[email protected] oracle]$ expdp \'powerdesk/testcrmfile\' directory=DIR_DUMP tables=bis_floor,bis_shop,bis_shop_conn,bis_store,bis_cont dumpfile=zhengyin.qu_bak_$(date +%Y%m%d)_02.dmp Export