题目


 

题解


这题用类似暴力+优化(划掉)的思想。

对于每个轨迹串,求出每一位向后的第一个0-9间某个数字的位置(如123112中3后面第1个2的位置为从左往右数第6个),复杂度O(Σn)=O(L)。

在dfs中枚举密码,相邻两位相同的在处理中合并(即不枚举1223,改为123)。

还有就是要注意,当位数为2或3时,若匹配成功则答案+3而不是+1。比如枚举23,可以有2333,2233,2223三种密码。枚举123,可以有1123,1223,1233三种。

最后就是细节问题了。

代码


 

 1 #include <stdio.h>
 2 #define N 1005
 3 int n,a[N],d[9],k[]={0,1,3,3,1},ans=0;char *s[N];
 4 struct sufarr {
 5     short a[10];
 6     void clear(){for(int i=0;i<10;++i) a[i]=0;}
 7 } *suf[N],tmp;
 8 inline void input() {
 9     scanf("%d",&n);
10     for(int i=0;i<n;++i) {
11         scanf("%d",a+i);
12         s[i]=new char[a[i]+5];
13         suf[i]=new sufarr[a[i]+5];
14         scanf("%s",s[i]+1);
15         tmp.clear();
16         for(int j=a[i];j;--j) {
17             suf[i][j]=tmp;
18             tmp.a[s[i][j]^48]=j;
19         }
20         suf[i][0]=tmp;
21     }
22 }
23 inline bool test(int len) {
24     int cnt,cur,u;
25     for(int i=0;i<n;++i) {
26         for(cur=0,cnt=1;cnt<=len;++cnt) {
27             u=suf[i][cur].a[d[cnt]];
28             if(!u) break;cur=u;
29         }
30         if(cnt<=len) return 0;
31     }
32     return 1;
33 }
34 void dfs(int t) {
35     for(int i=0;i<10;++i) {
36         if(i!=d[t-1]) {
37             d[t]=i;
38             if(test(t)) {
39                 ans+=k[t];
40                 if(t<4) dfs(t+1);
41             }
42         }
43     }
44 }
45 int main() {
46     input();
47     d[0]=-1;dfs(1);
48     printf("%d",ans);
49     return 0;
50 }

 

#include <OI必会>

using namespace OIer;

void 完结撒花() {

日常 %("czhou");

}

int main() {

完结撒花();

return 0;

}