题目描述
托米没有完成上一个任务,准备施展黑魔法推倒 1317
黑魔法咒语被描述为一个 长为 n 的,仅包含小写英文字母 'a'...'i' 的字符串,在托米所在的星球,魔法造成的每次有效伤害都是来自他的一个子序列,对于每一个 'a'... 'i' 的排列(共 9! 种),若作为咒语的子序列出现, 就会造成 1 的伤害
而咒语的总伤害为所有 'a'... 'i' 的排列造成的伤害值之和,托米能打出多少点的伤害,是否能击败 1317 呢?
输入描述:
一行输入一个字符串 s
输出描述:
一行输出一个数,表示伤害值
输入
aabcdefghi
输出
1
其实这道题只要暴力所有全排列,对于每个全排列judge一下就ok了
暴力全排列只需要调用next_permutation()函数就可以一行搞定
检测某个全排列是否在字符串中出现很显然不能O(n)暴力,会超时,考虑一个O(10)的检测方法
预处理dp[i][k]表示从第i个字符开始字母k最早出现的位置(如果不存在为-1),之后判定方法如下:
now = 1;
for(i=1;i<=9;i++)
{
now = dp[now][p[i]]+1;
if(now==0)
break;
}
if(now!=0) //存在
ans++;
搞定
总程序:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[3005][12];
char str[3005];
int a[3005], p[15];
int main(void)
{
int n, i, j, now, ans;
scanf("%s", str+1);
n = strlen(str+1);
for(i=n;i>=1;i--)
a[i] = str[i]-'a'+1;
memset(dp, -1, sizeof(dp));
for(i=n;i>=1;i--)
{
for(j=1;j<=9;j++)
dp[i][j] = dp[i+1][j];
dp[i][a[i]] = i;
}
for(i=1;i<=9;i++)
p[i] = i;
ans = 0;
while(1)
{
now = 1;
for(i=1;i<=9;i++)
{
now = dp[now][p[i]]+1;
if(now==0)
break;
}
if(now!=0) //存在
ans++;
if(next_permutation(p+1, p+10)==0)
break;
}
printf("%d\n", ans);
return 0;
}