C - Word Ladder (Toyota Programming Contest 2024#9 (AtCoder Beginner Contest 370))

题目链接:C - Word Ladder

题目:

样例:

分析:

不要被题目所吓到,一切长题目都是纸老虎。题目大意就是给你两个字符串s和t,一次只能更换一个字母,求s变到t更换的次数,并输出每次更换一个字母后的最小字典序字符串。题意好理解,可以直接暴力,大力出奇迹。但是有没有更好的方法呢?既然问了就说明是有的。最主要的是要搞清每次更换的是哪个字母。我们可以先考虑特殊情况,假设s中的每个字母都是大于等于t中对应的那个字母,如:s=bbb,t=aaa。第一次s=bbb更换有三种情况:abb bab bba 最小的那个是abb。第二次s=abb更换有两种:aab aba 最小的那个是aab。第三次s=aab可直接更换为t=aaa。可看出当s>=t时更换的次序是从左到右依次更换的。同理可知当s中的每个字母都是小于等于t中对应的那个字母时更换的次序是从右到左依次更换的。由特殊到一般,s中字母既有大于还有小于t中对应的字母时,如样例中:s=afwgebrw,t=oarbrenq。s中字母大于t中相应位置的下标为:12367,小于的为:045。而s到t更换的次序为:12367 540,首先是大于的从左往右,然后是小于的从右往左。知道这就好做了。我们可以用一个动态数组记录每次要改变字母的位置,然后改变就好了。当然也可以用双向队列deque来做,从后往前扫描,s中哪个字母>t中对应的字母是时插入队列的头部,小于时插入队列的尾部,这一套下来后可也得出大于的是从左往右的,小于的是从右往左的。话不多说直接上 code

GAME OVER!!!

END!

方法一:直接暴力 

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;

vector<string>ans;
signed main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	string s, t;
	int k; //s和t中不同的字母个数   
	cin >> s >> t;
	int n = s.size();
	while(s != t) {
		k ++;
		string idx(n, 'z');
		for(int i = 0; i < n; i++ ) {
			if(s[i] != t[i]) {
				string tmp = s;
				tmp[i] = t[i];
				idx = min(idx,tmp); //得到字典序最小的那个字符串 
			}
		}
		ans.push_back(idx);         //把每次最小的字符串加入到答案数组中 
		s = idx;                    //把这次修改后的字符串赋值给s 
	}
	cout << k << endl;
	for(auto i : ans)
		cout << i << endl;
	return 0;
}

方法二:记录位置

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;

signed main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	string s, t;
	cin >> s >> t;
	vector<string> ans;
	vector<int> x; //存要改变字母的下标 
	int n = s.size();
	for(int i = 0; i < n; i++ ) {//大于 从左往右 
		if(s[i] > t[i]) x.push_back(i);
	}
	for(int i = n - 1; i >= 0; i-- ) {//小于 从右往左 
		if(s[i] < t[i]) x.push_back(i);
	}
	int k = x.size(); 
	
	for(int i = 0;i < k; i++ ) {
		s[x[i]] = t[x[i]];
		ans.push_back(s);
	}
	cout << k << endl;
	for(auto i : ans) cout << i << endl; 
	return 0;
}

方法三:deque

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;

signed main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	string s, t;
	cin >> s >> t;
	deque<int> x;
	for(int i = s.size() - 1; i >= 0; i --) {//队列从后往前扫描 
		if(s[i] > t[i]) x.push_front(i);     //大于的插入头部 
		if(s[i] < t[i]) x.push_back(i);      //小于的插入尾部 
	}
	int k = x.size();
	cout << k << endl;
	for(auto i : x) {
		s[i] = t[i];
		cout << s << endl;
	}
	return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值