题目大意:
给你一个字符串,表示拥有的字符为长度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