uva 10716 Evil Straw Warts Live(贪心回文串)

这道题目我用了一上午才做出来,还是看的别人的思路,尽管没有看代码做的有点慢。代码能力还是得加强啊。思维

得缜密。不能想当然,要有根据,写上的代码要有精确度。省的以后还得慢慢调试

思路:贪心。每次都查看两端位置上的字母是否相等。若不相等就在里面查找能使他们相等且所需移动位置最少的那

个。然后交换。记录交换的距离,贪心的离最后一个由近及远找与第一个位置相等的。同理贪心从第一个位置找和最

后一个位置相等且离第一个位置近期的。

。感觉这样的方法确实能够,可是并不会证明这样的策略的正确性。。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<algorithm>

using namespace std;
int a[30];
string s;
void swap1(int x,int y)
{
	char ch = s[x];
	for(int i=x; i<y; i++)
	{
		s[i] = s[i+1];
	}
	s[y] = ch;
	return ;
}
void swap2(int x,int y)
{
	char ch = s[y];
	for(int i=y; i>x; i--)
	{
		s[i] = s[i-1];
	}
	s[x] = ch;
	return ;
}
int cost;
void solve()
{
	int i,j;
	for(i=0; i<(s.size()/2); i++)
	{
		//cout << "i = "<<i << endl;
		if(s[i]!=s[s.size()-1-i])
		{
			for(j=1; j<=s.size()-1-1-i-i; j++)
			{
				if(s[j+i]== s[s.size()-1-i])//推断是否和最后一个相等。若相等就放到对称位置
				{
					swap2(i,i+j);//准确写出移动函数
					//cout << s << endl;
					cost += j;//移动距离
					break;
				}
				else if(s[s.size()-1-i-j] == s[i])//推断是否和第一个相等。若相等就和最后一个互换。即它的最后一个位置(这里所说第一个位置是当前推断的位置不是所有序列的第一个)
				{
					swap1(s.size()-1-i-j,s.size()-1-i);//注意调用的移动函数是否可行
					//cout << s << endl;
					cost+= j;
					break;
				}
			}
		}
	}
	return ;
}
int main()
{
	int T,i;
	int ans;
	cin >> T;
	getchar();
	while(T--)
	{
		ans = 0;
		memset(a,0,sizeof(a));
		s.clear();
		cin >> s;
		getchar();
		for(i=0; i<s.size(); i++)
		{
			a[s[i]-'a']++;
		}
		int flag = 0;
		for(i=0; i<26; i++)//预处理能否够构成回文数
		{
			if(a[i]%2!=0)
			{
				ans++;
			}
		}
		cost = 0;
		if(ans > 1)
			cout << "Impossible" << endl;
		else
		{
			solve();
			cout << cost << endl;
		}
	}
	return 0;
}
时间: 2024-08-02 02:40:20

uva 10716 Evil Straw Warts Live(贪心回文串)的相关文章

UVA - 10716 - Evil Straw Warts Live (简单模拟)

UVA - 10716 Evil Straw Warts Live Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem D: Evil Straw Warts Live A palindrome is a string of symbols that is equal to itself when reversed. Given an

回文串区间dp

UVa 10739 String to Palindrome(经典回文串区间DP) 题意: 给定一个字符串,可以对其进行删除,插入,替换操作. 问最少经过几次操作,可以使这个字符串变成回文字符串. 思路: 看得别人的 题解,最优化问题,用较为直接的方法处理时发现情况很复杂,很多时候就要考虑动态规划了.先从整体出发,由大到小,看往少一个两个元素的情况进行最优递归,如何得到结果. (这里区间DP即是不断向两侧扩大规模) (1)如果最外层两个字符相同,s[0]==s[n],那么这两个字符外侧肯定不用考

Evil Straw Warts Live (Uva10716 回文串+贪心)

[原题] A palindrome is a string of symbols that is equal to itself when reversed. Given an input string, not necessarily a palindrome, compute the number of swaps necessary to transform the string into a palindrome. By swap we mean reversing the order

uva--10716Evil Straw Warts Live +回文串+贪心

题意: 输入一个字符串,我们可以交换这个字符串中的相邻字符:问至少经过多少步交换可以得到一个回文串:如果无论怎么交换都得不到回文串,输出"Impossible": 思路: 首先由回文串的定义和性质,可以得到两种不可能情况:1.当这个串长度为奇数时,如果出现次数为奇数次字母的数目不为1,则显然不可能.2.当这个串长度为偶数时,如果出现次数为奇数次字母的个数大于0,则不可能. 除去这两种不可能的情况后,这个串就一定可以转成回文串.我们只需要考虑0--len/2(len为串长)的部分,对于第

UVA10716 - Evil Straw Warts Live

题意:如果可以的话,使用最少的交换次数,使得字符串变成回文字符串. 思路: 1.首先我们可以先判断这个字符串是否有成为回文的可能性.当一个字符串中出现两个或两个以上的奇数个数的字符,那么这个字符串一定不能成为回文字符串. 2.之后就要讨论怎么使用最少的交换次数使得变成回文字符串.我们可以采取由外到内的方法,即先将头尾两端的字符交换成相同的,然后left++,right--,慢慢向内靠拢. 为了让交换次数最少,那么每次移动到左右两个端点的字符的交换次数也要最少.这样的话就要找相同字符第一次出现和最

UVA - 11584 划分字符串的回文串子串; 简单dp

/** 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34398 UVA - 11584 划分字符串的回文串子串: 简单dp 题目大意: 给一个字符串, 要求把它分割成若干个子串,使得每个子串都是回文串.问最少可以分割成多少个. 定义:dp[i]表示前0~i内的字符串划分成的最小回文串个数: dp[i] = min(dp[j]+1 | j+1~i是回文串); 先预处理flag[i][j]表示以i~j内的字符串为回文串

Uva 11584,划分成回文串

题目链接:https://uva.onlinejudge.org/external/115/11584.pdf 题意: 一个字符串,将它划分一下,使得每个串都是回文串,求最少的回文串个数. 分析: d(i)到第 i 个字符时的最优解(即最少划分为几个回文串),就有方程  d(i) = min(d(j)) + 1;(其中s[j+1,i]要是回文串). 这样一来,枚举就是O(n^2)的复杂度,如果按照普通的判断s[j+1,i]是否是回文串,时间复杂度为O(n^3);先用O(n^2)的复杂度预处理is

UVa 10617 Again Palindrome(回文串区间DP)

UVa 10617 Again Palindrome(经典回文串区间DP) 题意: 给定一个字符串s,对s进行删除操作,使得剩下的子串是回文字符串,问最多有多少种这种子串. 思路: 涉及到回文字符串,首先要想到的肯定是区间DP,如何写出状态转移方程? 直接从题意切入:dp[i, j]表示区间[i, j]最多有多少个这样的子串. 1. s[i] == s[j] 去掉s[i],则一个子问题就是dp[i+1, j]; 去掉s[j],另一个子问题就是dp[i, j-1]; 显然这两个子问题是会有重叠的,

UVa 11584 划分成回文串

https://vjudge.net/problem/UVA-11584 题意: 给出一串字符,把它划分成尽量少的回文串. 思路: 用d[i]表示划分到i时所能划分的最小个数,转移方程为d[i]=min{d[i],d[j]+1},当然前提是j+1~i是回文串,我们可以预处理计算出所有的回文串,这样转移时就比较方便. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<s