牛客练习赛23 托米的咒语
托米没有完成上一个任务,准备施展黑魔法推倒 1317
而咒语的总伤害为所有 'a'... 'i' 的排列造成的伤害值之和,托米能打出多少点的伤害,是否能击败 1317 呢?
黑魔法咒语被描述为一个 长为 n 的,仅包含小写英文字母 'a'...'i' 的字符串,在托米所在的星球,魔法造成的每次有效伤害都是来自他的一个子序列,对于每一个 'a'... 'i' 的排列(共 9! 种),若作为咒语的子序列出现, 就会造成 1 的伤害
输入描述:
一行输入一个字符串 s
输出描述:
一行输出一个数,表示伤害值
备注:
|s| ≤ 3000
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <string> 6 #include <string> 7 #include <map> 8 #include <cmath> 9 #include <set> 10 #include <algorithm> 11 using namespace std; 12 typedef long long ll; 13 const int N=1e5+7; 14 char p[10]="abcdefghi"; 15 string s; 16 int dp[3100][10],num[10]; 17 ll ans; 18 int flag; 19 int main() 20 { 21 cin>>s; 22 s=' '+s; 23 for(int i=s.size()-1;i>=0;i--){ 24 for(int j=0;j<9;j++){ 25 dp[i][j]=num[j];//例如dp[1][0]:输入字符串里第一个 26 //字符串右边‘a’距离1最近的位置。 27 /* 28 为什么要最近的 29 举个例子: 30 abcbde 31 a 若匹配第二个b就无法查找到abcde,但是abcde是存在的. 32 也就是说离彼此最近的都无法找到,就一定不存在了. 33 */ 34 } 35 if(i!=0) num[s[i]-'a']=i;//不断更新. 36 } 37 /* 38 ''aabcdefghi 39 0 0 0 0 0 0 0 0 0 0 40 0 0 0 0 0 0 0 0 10 0 41 0 0 0 0 0 0 0 9 10 0 42 0 0 0 0 0 0 8 9 10 0 43 0 0 0 0 0 7 8 9 10 0 44 0 0 0 0 6 7 8 9 10 0 45 0 0 0 5 6 7 8 9 10 0 46 0 0 4 5 6 7 8 9 10 0 47 0 3 4 5 6 7 8 9 10 0 48 2 3 4 5 6 7 8 9 10 0 49 1 3 4 5 6 7 8 9 10 0 50 */ 51 ans=0; 52 do{ 53 flag=0; 54 for(int i=0;i<9;i++){ 55 flag=dp[flag][p[i]-'a']; 56 if(!flag) {ans--;break;} 57 } 58 ans++; 59 }while(next_permutation(p,p+9));//检测每个全排列字符串是否存在. 60 printf("%lld\n",ans); 61 return 0; 62 }