牛客练习赛23: D. 托米的咒语(暴力)

题目描述

托米没有完成上一个任务,准备施展黑魔法推倒 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;
}

猜你喜欢

转载自blog.csdn.net/jaihk662/article/details/81254833
今日推荐