试题 基础练习 完美的代价 C语言

资源限制

内存限制:512.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s

问题描述

  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)

输入格式

  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母

输出格式

  如果可能,输出最少的交换次数。
  否则输出Impossible

样例输入

5
mamad

样例输出

3

思路:1.贪心算法   2.从左到右枚举每个字符,移动对应字符。个数为单的字符放中间。

贪心算法(Greedy Algorithm)是一种在求解问题时,每一步都选择当前最优解,以期望最终得到全局最优解的算法思想。贪心算法的基本思想可以总结为“每一步都做出一个局部最优的选择,最终就能得到全局最优解”。

贪心算法通常包含以下关键步骤:

找到可选的子问题: 首先,将原问题拆分成一系列可选的子问题或决策。

找到局部最优解: 对每个子问题,找到一个局部最优解。这个局部最优解应该是一个贪心选择,即在当前状态下选择最优的方式。

合并子问题的解: 将各个子问题的局部最优解合并起来,得到原问题的解。

检查解的有效性: 最后,检查得到的解是否满足问题的约束和要求。如果满足,就认为得到了问题的解。                 
原文链接:https://blog.csdn.net/AlgorithmHero/article/details/132460794

代码:

法一

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int n, flag = 0, ans = 0;
	  int p,i,k,j;
    char *str;
    scanf("%d", &n);
    str = (char*)malloc(n * sizeof(char)+1); 
    scanf("%s", str);
    j = n - 1;
	  int sign = 0;
    for( i = 0; i < j; i++)
    {
        for( k = j; k >= 0; k--)
        {
            if(k == i)
            {
                flag++;
                if(n % 2 == 0 || flag > 1)
                {
                    printf("Impossible\n");
                    return 0;
                }
              ans += n/2 - i;
  
              break;
              
            }
            else if(str[k] == str[i])
            {
                for( p = k; p < j; p++)
                {
                    str[p] = str[p + 1];
                    ans++;
                }
                str[j] = str[i];
                j--;
                break;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

  详细记录

评测点序号评测结果得分CPU使用内存使用下载评测数据
1正确10.000ms2.667MB输入 输出
2正确10.000ms2.476MB输入 输出
3正确10.000ms2.464MB输入 输出
4正确10.000ms2.468MB输入 输出
5正确10.000ms2.464MB输入 输出
6正确10.000ms2.480MB输入 输出
7正确10.000ms2.476MB输入 输出
8正确10.000ms2.468MB输入 输出
9正确10.000ms2.476MB输入 输出
10正确10.000ms2.488MB输入 输出

法二:

  1. 统计每个字母的个数判断是否能构成回文,奇数字母超过1直接输出impossible,否则准备计算交换次数
  2. 从第一个字母到中间位置开始交换。
    交换有两种情况:中间位置字母、非中间位置字母。奇数字母移到中间,非中间字母移到对称位置,分别加上对应的移动次数。
#include<stdio.h>

int change(char str[], char x, int len){
	int i, j, k, count = 0;
	for(i = 0; i < len/2 ; i++){
		if(str[i] == x){
			for(j = i; j < len-i-1; j++){
				if(str[j] == str[len - i - 1])
					break;
			}
			count += j - i;
			for(k = j; k > i; k--)
				str[k] = str[k-1];
			str[i] = str[len - 1 - i];
		}
		else{
			for(j=len-1-i; j>=i; j--){
				if(str[i] == str[j])
					break;
			}
			count += len - 1 - i - j;
			for(k = j; k < len - 1 - i; k++)
				str[k]=str[k+1];
			str[len - i - 1]=str[i];
		}
	}
	return count;
}

int main(){
    char str[8000]={0}, x;
    int len, b[26]={0}, i, j, k = 0;
    scanf("%d", &len);
    getchar();
    for(i = 0; i < len; i++){
    	scanf("%c", &str[i]);
	}
	for(i = 0; i < len; i++){
		j = str[i]-'a';
		b[j]++;
	}
	for(j = 0; j < 26; j++){
		if(b[j] % 2 != 0){
			k++;
			x = j + 'a';
		}
	}
	if( k>=2 ){
		printf("Impossible\n");
	}
	else
		printf("%d\n", change(str, x, len));
    return 0; 
}

 

详细记录
评测点序号评测结果得分CPU使用内存使用下载评测数据
1正确10.000ms2.707MB输入 输出
2正确10.000ms2.507MB输入 输出
3正确10.000ms2.503MB输入 输出
4正确10.000ms2.507MB输入 输出
5正确10.000ms2.507MB输入 输出
6正确10.000ms2.507MB输入 输出
7正确10.0015ms2.507MB输入 输出
8正确10.000ms2.507MB输入 输出
9正确10.000ms2.507MB输入 输出
10正确10.000ms2.507MB输入 输出

法三:

90%正确

#include<stdio.h>  
#include<stdlib.h>  
int main() 
{
     int i,j,l,n,k,sum=0,flat=1,c=-1;
     char *a;
     scanf("%d",&n);
     a=(char *)malloc(n*sizeof(char));
     scanf("%s",a);
	   j=n-1;  
     //利用贪心的思想,将每个遍历的字符找到后面与他相同的然后交换到正确的位置时所需的交换次数   
     for(i=0;i<j;i++){
         for(k=j;k>=i;k--){
             if(k==i){ 
                 if(n%2==0||c!=-1){
                     flat=0;
                     break;
                 }
                 c=1;
                 sum=sum+n/2-i;
                break;
            }
            if(a[k]==a[i]){
                 for(l=k;l<j;l++){  
                     a[l]=a[l+1];  
                }  
                a[j]=a[i];  
                sum=sum+j-k;  
                 j--;  
                 break;  
            }  
         }  
         if(flat==0){
             break;
         } 
     }  
     if(flat==0)
       printf("Impossible");
     else if(sum==0)
         printf("0");
     else 
         printf("%d\n",sum);
     return 0;  
}

详细记录

评测点序号评测结果得分CPU使用内存使用下载评测数据
1运行错误0.000ms2.718MB输入 输出
2正确10.000ms2.511MB输入 输出
3正确10.000ms2.503MB输入 输出
4正确10.000ms2.503MB输入 输出
5正确10.000ms2.503MB输入 输出
6正确10.000ms2.503MB输入 输出
7正确10.000ms2.511MB输入 输出
8正确10.000ms2.503MB输入 输出
9正确10.000ms2.511MB输入 输出
10正确10.000ms2.511MB输入 输出

 

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值