hdu 6739 Invoker
Invoker
Problem Description
在 dota2 中有一个叫做祈求者(Invoker)的英雄,在游戏中他有三个基础技能:冰(Quas),雷(Wex),火(Exort),每施展一个技能就可以获得相应属性的一个法球(element)。
但是祈求者同时最多只能有三个法球,即如果他在有三个法球的状态下又使用了某个法球技能,那么他会获得该法球,并失去之前三个法球中最先获得的一个。
不难得出,祈求者身上的三个法球的**无顺序**组合有 10 种,每一种都对应着一个组合技能:
1. 急速冷却(Cold Snap),无序组合 QQQ,用 Y 表示
2. 幽灵漫步(Ghost Walk),无序组合 QQW,用 V 表示
3. 寒冰之墙(Ice Wall),无序组合 QQE,用 G 表示
4. 电磁脉冲(EMP),无序组合 WWW,用 C 表示
5. 强袭飓风(Tornado),无序组合 QWW,用 X 表示
6. 灵动迅捷(Alacrity),无序组合 WWE,用 Z 表示
7. 阳炎冲击(Sun Strike),无序组合 EEE,用 T 表示
8. 熔炉精灵(Forge Spirit),无序组合 QEE,用 F 表示
9. 混沌陨石(Chaos Meteor),无序组合 WEE,用 D 表示
10. 超震声波(Deafening Blast),无序组合 QWE,用 B 表示
当祈求者拥有三个法球的时候,使用元素祈唤(Invoke)技能,用 R 表示,便可获得当前法球组合所对应的技能,同时原有的三个法球也不会消失,先后顺序的状态也不会改变。
现在给定一个技能序列,你想按照给定的顺序将他们一个一个地祈唤出来,同时你想用最少的按键来达到目标,所以你想知道对于给定的一个技能序列,最少按多少次键才能把他们都祈唤出来。
注意:游戏开始的时候,祈求者是没有任何法球的。
Input
仅一行一个字符串 s,表示技能序列。其中所有字母都是大写,且在 {B,C,D,F,G,T,V,X,Y,Z} 内。
1≤|s|≤105
Output
仅一行一个正整数,表示最少按键次数。
Sample Input
XDTBV
Sample Output
14
Hint
一种按键最少的方案为:QWWREERERWQRQR
思路:暴力DP,把当前可行的情况枚举出来,然后跟之前枚举的匹配进行递推。
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 #include<queue>
10 #include<list>
11 #include<stack>
12 //#include<unordered_map>
13 using namespace std;
14 #define ll long long
15 #define dd cout<<endl
16 #define lll __int128
17 const int mod=1e9+7;
18 const int inf=1e9+7;
19
20 const int maxn=1e6+10;
21
22 int dp[maxn][10];
23
24 int main()
25 {
26 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
27
28 string str;
29
30 while(cin>>str)
31 {
32 memset(dp,0X3f3f3f,sizeof(dp));
33
34 string last[6];
35
36 string now[6];
37
38 for(int i=0;i<str.size();i++)
39 {
40 if(str[i]=='Y')
41 {
42 now[0]="QQQ",now[1]="QQQ",now[2]="QQQ";
43 now[3]="QQQ",now[4]="QQQ",now[5]="QQQ";
44 }
45 else if(str[i]=='V')
46 {
47 now[0]="QQW",now[1]="QWQ",now[2]="QQW";
48 now[3]="QWQ",now[4]="WQQ",now[5]="WQQ";
49 }
50 else if(str[i]=='G')
51 {
52 now[0]="EQQ",now[1]="EQQ",now[2]="QEQ";
53 now[3]="QQE",now[4]="QEQ",now[5]="QQE";
54 }
55 else if(str[i]=='C')
56 {
57 now[0]="WWW",now[1]="WWW",now[2]="WWW";
58 now[3]="WWW",now[4]="WWW",now[5]="WWW";
59 }
60 else if(str[i]=='X')
61 {
62 now[0]="QWW",now[1]="QWW",now[2]="WQW";
63 now[3]="WWQ",now[4]="WQW",now[5]="WWQ";
64 }
65 else if(str[i]=='Z')
66 {
67 now[0]="EWW",now[1]="EWW",now[2]="WEW";
68 now[3]="WWE",now[4]="WEW",now[5]="WWE";
69 }
70 else if(str[i]=='T')
71 {
72 now[0]="EEE",now[1]="EEE",now[2]="EEE";
73 now[3]="EEE",now[4]="EEE",now[5]="EEE";
74 }
75 else if(str[i]=='F')
76 {
77 now[0]="EEQ",now[1]="EQE",now[2]="EEQ";
78 now[3]="EQE",now[4]="QEE",now[5]="QEE";
79 }
80 else if(str[i]=='D')
81 {
82 now[0]="EEW",now[1]="EWE",now[2]="EEW";
83 now[3]="EWE",now[4]="WEE",now[5]="WEE";
84 }
85 else if(str[i]=='B')
86 {
87 now[0]="EQW",now[1]="EWQ",now[2]="QEW";
88 now[3]="QWE",now[4]="WEQ",now[5]="WQE";
89 }
90
91 if(i==0)
92 {
93 for(int j=0;j<6;j++)
94 {
95 dp[i][j]=3;
96 }
97 }
98 else
99 {
100 for(int j=0;j<6;j++)
101 {
102 for(int k=0;k<6;k++)
103 {
104 string pre=last[k],nxt=now[j];
105
106 int cnt;
107
108 if(pre[0]==nxt[0]&&pre[1]==nxt[1]&&pre[2]==nxt[2])
109 cnt=3;
110 else if(pre[1]==nxt[0]&&pre[2]==nxt[1])
111 cnt=2;
112 else if(pre[2]==nxt[0])
113 cnt=1;
114 else
115 cnt=0;
116
117 dp[i][j]=min(dp[i][j],dp[i-1][k]+(3-cnt));
118
119 }
120
121 }
122 }
123
124 for(int j=0;j<6;j++)
125 {
126 last[j]=now[j];
127 }
128
129 }
130
131 int minn=dp[(int)str.size()-1][0];
132
133 for(int i=0;i<6;i++)
134 {
135 if(dp[(int)str.size()-1][i]<minn)
136 minn=dp[(int)str.size()-1][i];
137 }
138
139 cout<<minn+str.size()<<endl;
140
141 }
142
143 return 0;
144 }