题解- P 4290 [ H A O I 2008 ] P4290 [HAOI2008] P4290[HAOI2008]玩具取名
- 在复习区间 D P DP DP的时候做到题目觉得挺好的就做了下,差点做不出来。
题目意思
S o l Sol Sol
这道题目我们先设两个数组 f i , j , k f_{i,j,k} fi,j,k表示 [ i , j ] [i,j] [i,j]能否用 W , I , N , G W,I,N,G W,I,N,G得到。再设 g i , j , k g_{i,j,k} gi,j,k表示 k k k是否能用 i , j i,j i,j得到(这在读入就可以预处理出来)。
那么 f i , j , k f_{i,j,k} fi,j,k怎么处理出来呢?
f
i
,
j
,
k
=
1
f_{i,j,k}=1
fi,j,k=1
(
f
i
,
p
,
o
=
f
p
+
1
,
j
,
p
=
1
\ (f_{i,p,o}=f_{p+1,j,p}=1
(fi,p,o=fp+1,j,p=1且
g
o
,
p
,
k
)
\ g_{o,p,k})
go,p,k)
f
i
,
j
,
k
=
1
f_{i,j,k}=1
fi,j,k=1
(
i
=
j
,
s
i
=
k
)
\ (i=j,s_i=k)
(i=j,si=k)
于是就 O ( n 3 × 64 ) O(n{^3} \times 64) O(n3×64) ,其中 64 64 64就是枚举 o , p , k o,p,k o,p,k即可。
C o d e Code Code
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
const int M=205;
int n,W,I,N,G,f[M][M][5],g[5][5][5];
char c[M];
inline int C(char c)
{
if(c=='W') return 1;
if(c=='I') return 2;
if(c=='N') return 3;
if(c=='G') return 4;
}
inline char S(int c)
{
if(c==1) return 'W';
if(c==2) return 'I';
if(c==3) return 'N';
if(c==4) return 'G';
}
int main()
{
W=read();
I=read();
N=read();
G=read();
for ( int i=1;i<=W;i++ )
{
char ch[5];
scanf("%s",ch+1);
g[C(ch[1])][C(ch[2])][1]=1;
}
for ( int i=1;i<=I;i++ )
{
char ch[5];
scanf("%s",ch+1);
g[C(ch[1])][C(ch[2])][2]=1;
}
for ( int i=1;i<=N;i++ )
{
char ch[5];
scanf("%s",ch+1);
g[C(ch[1])][C(ch[2])][3]=1;
}
for ( int i=1;i<=G;i++ )
{
char ch[5];
scanf("%s",ch+1);
g[C(ch[1])][C(ch[2])][4]=1;
}
scanf("%s",c+1);
n=strlen(c+1);
for ( int i=1;i<=n;i++ ) f[i][i][C(c[i])]=1;
for ( int l=2;l<=n;l++ )
for ( int i=1;i+l-1<=n;i++ )
{
int j=i+l-1;
for ( int k=i;k<j;k++ )
for ( int o=1;o<=4;o++ )
if(f[i][k][o])
for ( int p=1;p<=4;p++ )
if(f[k+1][j][p])
for ( int q=1;q<=4;q++ )
if(g[o][p][q])
f[i][j][q]=1;
}
int ff=1;
for ( int i=1;i<=4;i++ )
if(f[1][n][i])
{
putchar(S(i));
ff=0;
}
if(!ff) return 0;
printf("The name is wrong!\n");
return 0;
}