题目
题解
这题用类似暴力+优化(划掉)的思想。
对于每个轨迹串,求出每一位向后的第一个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;
}