题目大意:给出一个字符串s,从第一个字符开始,每次可以移动到任意一个字符,费用为两个字符的差值,问在费用最低的情况下,怎么用最多的步数到字符串最后一个字符
思路:费用最小值就等于第一个字符到最后一个字符的费用,要想步数最多,就要依次经过头尾两个字符中间的字符,用一个结构体储存字符和他在字符串中的位置,如果头字符大于尾字符,就按字符从大到小排序,否则按从小到大排序,然后遍历排序后的数组,找到头元素后,记录步数,将字符位置记录到数组里,知道找到尾字符后退出循环
#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 2e5 + 5;
struct ch
{
char c;
int po;
}a[N];
int p[N];
bool cmp(ch a, ch b)
{
if (a.c == b.c)
return a.po < b.po;
return a.c > b.c;
}
bool cmp2(ch a, ch b)
{
if (a.c == b.c)
return a.po < b.po;
return a.c < b.c;
}
int main()
{
int t;
cin >> t;
while (t--)
{
string s;
cin >> s;
int len = s.length();
int cnt = 0;
for (int i = 0; i < len; i++)
{//a储存字符和字符的位置
a[++cnt].c = s[i];
a[cnt].po = cnt;
}
if (s[0] > s[len - 1])
{//头字符大于尾字符就从大到小排序
sort(a + 1, a + len + 1, cmp);
}
else
{
sort(a + 1, a + len + 1, cmp2);
}
printf("%d", abs(s[0] - s[len - 1]));
int ans = 0;
bool temp = 0;
for (int i = 1; i <= len; i++)
{
if (!temp&&a[i].c == s[0])
{//找到了头字符
temp = 1;
p[++ans] = a[i].po;
}
else if (a[i].po == len)
{//找到了尾字符
p[++ans] = a[i].po;
break;
}
else if (temp)
{//头字符和尾字符之间的元素
p[++ans] = a[i].po;
}
}
printf(" %d\n", ans);
for (int i = 1; i <= ans; i++)
{
printf("%d ", p[i]);
}
printf("\n");
}
return 0;
}