2019焦作-Invoker-(线性dp)

I

题意:
就是一共有QWE3个法球,然后存满3个法球按一次R,就可以放出对应的技能,当然一个技能对应3个法球,顺序无所谓。然后当有3个法球的时候,再放一个法球,那么最开始的法球就会消失。现在给你一个技能顺序,问你最少要按多少次键盘。

思考:
刚开始我没看到技能的法球是任意的,直接以为是模拟。发现是任意的之后,这肯定不能模拟了,也不能搜索,只能就是dp,然后发现技能就3个字母所以也就6中状态,所以dp[i][j]代表走到i的j状态的最小操作次数。不同的状态用一下permutation就行了。值得注意的是,per必须是字符是从小到大排序的,当时我以为QWE就是排序的,实际上E明明更小,可能游戏打多了。

代码:

int T,n,m,k;
int va[N];
char s[N];
int dp[N][10];
map<char,string> mp;

int get(string s1,int t1,string s2,int t2)
{
	do{
		if(--t1==0) break;
	}while(next_permutation(s1.begin(),s1.end()));
	do{
		if(--t2==0) break;
	}while(next_permutation(s2.begin(),s2.end()));
	char a1 = s1[0],b1 = s1[1],c1 = s1[2];
	char a2 = s2[0],b2 = s2[1],c2 = s2[2];
	if(a1==a2&&b1==b2&&c1==c2) return 0;
	if(b1==a2&&c1==b2) return 1;
	if(c1==a2) return 2;
	return 3;
}

signed main()
{
	IOS;
	mp['Y'] = "QQQ";mp['V'] = "QQW";mp['G'] = "QQE";
	mp['C'] = "WWW";mp['X'] = "QWW";mp['Z'] = "WWE";
	mp['T'] = "EEE";mp['F'] = "QEE";mp['D'] = "WEE";mp['B'] = "QWE";
	for(auto t:mp)
	{
		string now = t.se;
		sort(now.begin(),now.end());mp[t.fi] = now;
	}
	cin>>s+1;n = strlen(s+1);
	for(int i=1;i<=n;i++) for(int j=1;j<=6;j++) dp[i][j] = inf;
	for(int i=1;i<=6;i++) dp[1][i] = 3;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=6;j++)
		{
			for(int k=1;k<=6;k++)
			dp[i][j] = min(dp[i][j],dp[i-1][k]+get(mp[s[i]],j,mp[s[i-1]],k));
		}
	}
	int minn = inf;
	for(int i=1;i<=6;i++) minn = min(minn,dp[n][i]);
	cout<<minn+n;
	return 0;
}

总结:
多多思考呀。注意细节。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值