HDU - 6739 Invoker(DP)
In dota2, there is a hero named Invoker. He has 3 basic skills in the game, which are Quas, Wex and Exort. Once he launches a basic skill, he will gain the corresponding element, where Quas gives “Q”, Wex gives “W” and Exort gives “E”.
Invoker can’t have more than 3 elements simultaneously. If he launches a basic skill when he already owns 3 elements, he will get the corresponding element and lose the element he gained the earliest.
As can be seen, there are 10 unordered combinations of 3 elements in 3 types, each represents a special skill, which are as follows:
Cold Snap: unordered element combination “QQQ”, denoted by “Y”
Ghost Walk: unordered element combination “QQW”, denoted by “V”
Ice Wall: unordered element combination “QQE”, denoted by “G”
EMP: unordered element combination “WWW”, denoted by “C”
Tornado: unordered element combination “QWW”, denoted by “X”
Alacrity: unordered element combination “WWE”, denoted by “Z”
Sun Strike: unordered element combination “EEE”, denoted by “T”
Forge Spirit: unordered element combination “QEE”, denoted by “F”
Chaos Meteor: unordered element combination “WEE”, denoted by “D”
Deafening Blast: unordered element combination “QWE”, denoted by “B”
When Invoker owns 3 elements, he can launch the invoking skill, denoted by “R”, to gain the special skill according to the elements he currently owns. After invoking, the elements won’t disappear, and the chronological order of the 3 elements won’t change.
Now given a sequence of special skills, you want to invoke them one by one with using the minimum number of basic skills(Q,W,E) and invoking skill®. Print the minimum number in a single line.
At the beginning, Invoker owns no elements. And you should re-invoke the special skills even if you have already invoked the same skills just now.
Input
Input a single line containing a string s (1 ≤ |s| ≤ 100 000) that only contains uppercase letters in {B, C, D, F, G, T, V, X, Y, Z}, denoting the sequence of special skills.
Output
Output a single line containing a positive integer, denoting the minimum number of skills to launch.
在 dota2 中有一个叫做祈求者(Invoker)的英雄,在游戏中他有三个基础技能:冰(Quas),雷(Wex),火(Exort),每施展一个技能就可以获得相应属性的一个法球(element)。
题目大意
但是祈求者同时最多只能有三个法球,即如果他在有三个法球的状态下又使用了某个法球技能,那么他会获得该法球,并失去之前三个法球中最先获得的一个。
不难得出,祈求者身上的三个法球的无顺序组合有 10 种,每一种都对应着一个组合技能:
- 急速冷却(Cold Snap),无序组合 QQQ,用 Y 表示
- 幽灵漫步(Ghost Walk),无序组合 QQW,用 V 表示
- 寒冰之墙(Ice Wall),无序组合 QQE,用 G 表示
- 电磁脉冲(EMP),无序组合 WWW,用 C 表示
- 强袭飓风(Tornado),无序组合 QWW,用 X 表示
- 灵动迅捷(Alacrity),无序组合 WWE,用 Z 表示
- 阳炎冲击(Sun Strike),无序组合 EEE,用 T 表示
- 熔炉精灵(Forge Spirit),无序组合 QEE,用 F 表示
- 混沌陨石(Chaos Meteor),无序组合 WEE,用 D 表示
- 超震声波(Deafening Blast),无序组合 QWE,用 B 表示
当祈求者拥有三个法球的时候,使用元素祈唤(Invoke)技能,用 R 表示,便可获得当前法球组合所对应的技能,同时原有的三个法球也不会消失,先后顺序的状态也不会改变。
现在给定一个技能序列,你想按照给定的顺序将他们一个一个地祈唤出来,同时你想用最少的按键来达到目标,所以你想知道对于给定的一个技能序列,最少按多少次键才能把他们都祈唤出来。
注意:游戏开始的时候,祈求者是没有任何法球的。
Input
仅一行一个字符串 s,表示技能序列。其中所有字母都是大写,且在 {B,C,D,F,G,T,V,X,Y,Z} 内。
1≤|s|≤105
Output
仅一行一个正整数,表示最少按键次数。
思路
首先要释放s.lenth()个技能,即要按下s.lenth()个R键
对于一个长度为3的字符串 一共有六种排列,我们可以以123来举例:
123
132
213
231
312
321
那么我们可以用dp[i][j]来表示第i个技能以第j中排列顺序释放时所需要的最小按键次数(不包括R键)
由此可以线性dp求解
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
#define MOD 1000000007
#define PI 3.1415926535898
#define INF 0x3f3f3f3f
#define MAXN 80000080
const double EPS = 1e-8;
LL read()
{
LL x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch>'9')
{
if (ch == '-')
{
w = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return w * x;
}
string a,s[11];
int mp[15][15];
bool ok=0;
LL sum=0;
int g(char c)
{
if(c=='Y')
return 1;
if(c=='V')
return 2;
if(c=='G')
return 3;
if(c=='C')
return 4;
if(c=='X')
return 5;
if(c=='Z')
return 6;
if(c=='T')
return 7;
if(c=='F')
return 8;
if(c=='D')
return 9;
if(c=='B')
return 10;
}
int dp[100000][7];
int xx[7][4]={{0,0,0,0,},{0,1,2,3},{0,1,3,2},{0,2,1,3},{0,2,3,1},{0,3,1,2},{0,3,2,1}};
int f(int x,int y,int ax,int ay)
{
char aa[4],bb[4];
for(register int i=1;i<=3;i++)
{
aa[i]=s[x][xx[ax][i]];
bb[i]=s[y][xx[ay][i]];
}
int s=0;
for(register int i=1;i<=3;i++)
{
bool ok=1;
for(register int j=1;j<=i;j++)
{
if(aa[3-i+j]!=bb[j])
{
ok=0;
break ;
}
}
if(ok)
s=i;
}
return 3-s;
}
int main()
{
s[1]="AQQQ";
s[2]="AQQW";
s[3]="AQQE";
s[4]="AWWW";
s[5]="AQWW";
s[6]="AWWE";
s[7]="AEEE";
s[8]="AQEE";
s[9]="AWEE";
s[10]="AQWE";
while(cin>>a)
{
memset(dp,0x3f3f3f,sizeof(dp));
sum+=a.length();
for(register int i=1;i<=6;i++)
{
dp[0][i]=3;
}
for(register int i=1;i<a.length();i++)
{
for(register int x=1;x<=6;x++)
{
for(register int y=1;y<=6;y++)
{
// printf("%c %c\n",a[i-1],a[i-1]);
// printf("dp[%d][%d]=min(%d+%d,%d)\n",i,y,dp[i-1][x],f(g(a[i-1]),g(a[i-1]),x,y),dp[i][y]);
dp[i][y]=min(dp[i-1][x]+f(g(a[i-1]),g(a[i]),x,y),dp[i][y]);
}
}
}
int mi=0x3f3f3f;
for(register int i=1;i<=6;i++)
{
mi=min(mi,dp[a.length()-1][i]);
}
cout<<sum+mi<<endl;
sum=0;
}
return 0;
}