8.5 算法设计与优化策略

8.5 算法设计与优化策略

我们将会在这一章中介绍一些经典问题的处理方法和解决策略。


8-1 煎饼 (UVA 120)

有一叠煎饼正在锅里,煎饼共有n张,每张都有一个数字,代表它的大小。厨房每次可以选择一个数k,把从锅底开始数第k张上面的煎饼全部翻转,即原来在上面的煎饼现在到了下面。

现在需要你设计一种方法使得所有的煎饼按照从小到大排序(即上面的煎饼最小)。输入时,各个煎饼按照从上到下的顺序给出。

分析:仔细观察的话我们可以发现这道题是需要我们设计出一种,而不是设计出最短的一种。这里的基本操作类似于“翻转一个连续的子序列”,我们很自然地可以会想到排序中所学过的冒泡排序,每次通过“翻转”将最大的元素放到数组的最右边,然后不断地“冒泡”就可以了。

这个题的输入实际没有给出n,所以需要按照字符串处理。首先将字符串按照空格分割:

void init(){
   stringstream ss(s); string p; 
	while (getline(ss,p,' ')){
   size++; a[size]=string_number(p);}
}

将分割后的字符串转化为数字的函数如下:

int string_number(string x){
   int sum=0; 
	for (int i=0;i<x.size();sum=sum*10+x[i]-'0',i++); return sum; 
}

上面这两个不会的或者代码看不懂的,找个坑把自己埋了吧。

还有一个翻转“煎饼”的函数:

//翻转函数如下,这里用类似于指针的方法处理的 
void cake_reserve(int k){
   int l=1,r=size+1-k; while (r-l>0){
   swap(a[r],a[l]);l++;r--;} }

到这里我们的准备工作就好了,接下来就做翻转就可以了:

void solve(int p){
   //p表示当前寻找第size+1-p大的元素的位置 
	//p=1时,即不需要再向下进行调整了,max表示前size+1-p的元素的最大值,pos表示该最大值的位置 
	if (p==1) {
   cout<<"0"; return;} int pos=1,max=a[1];
	for (int i=2;i<=p;i++) if(max<a[i]){
   max=a[i]; pos=i;}
	if (pos==p) solve(p-1);//如果当前第size+1-p大的元素已经在正确位置,就找第size-p大的元素 
	else{
   //找到了最大值的位置后,我们可以先将这个元素"翻转"到第一个,再翻转到查询序列的最后一个位置
	//如果pos=1时,就不需要翻转到第一个了,这里我为了大家看的方便一点,就全部打印出来了 
		if (pos!=1){
   cake_reserve(size+1-pos); cout<<size+1-pos<<endl; print_ans();} 
		cake_reserve(size+1-p); cout<<size+1-p<<endl; print_ans(); solve(p-1); 
	}
}

这里难点不多,容易出错的地方我个人感觉就是k和位置的转化。完整代码和结果如下:

#include<iostream>
#include<sstream>
#include<algorithm>
using namespace std;
string s; int a[31],size=0;
int string_number(string x){
   int sum=0; 
	for (int i=0;i<x.size();sum=sum*10+x[i]-'0',i++); return sum; 
}//将字符串按照空格分割开,转化为数字给存储起来 
void init(){
   stringstream ss(s); string p; 
	while (getline(ss,p,' '))</
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值