算法竞赛入门经典

开始接触ACM,老师推荐了紫皮书,但是C++渣渣的我读题都很费劲,搜罗博主文章发现几乎都是 原题+代码 。现尽己所能整理,比较啰(xiang)嗦(xi),希望能对同起步小白有所帮助,嘻嘻。

STL初步:不定长数组:vector

什么是vector?

向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。

原题目

从左到右有n个木块,编号为0~n-1,要求模拟以下4种操作(下面的a和b都是木块编
号)。
move a onto b:把a和b上方的木块全部归位,然后把a摞在b上面。
move a over b:把a上方的木块全部归位,然后把a放在b所在木块堆的顶部。
pile a onto b:把b上方的木块全部归位,然后把a及上面的木块整体摞在b上面。
pile a over b:把a及上面的木块整体摞在b所在木块堆的顶部。

遇到quit时终止一组数据。a和b在同一堆的指令是非法指令,应当忽略。

Sample Input
10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit
Sample Output
0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:
————————————————

【题目解释】

第一步:循规蹈矩的把木块一个一个的放在其相应位置上,一萝卜一坑儿。

第二步:开始变换位置

这里把3放到了2上 5,8 放到了6 上。
如此变换,回头看题发现有5中操作:

  • move
  • onto
  • over
  • pile:一挪挪一堆
  • 归位:放回他自己的坑儿里。(仅一个)
  • 堆:题目中所说的堆,有可能指一个木块,也有可能指一堆木块。

【 分析】

每个木块堆的高度(木块个数)不确定,所以用vector来保存很合适;而木块堆的个数不超过n,所以用一个数组来存就可以了。

代码及解释

main函数(代码极简)

#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
const int maxn = 30;
int n;
vector<int> pile[maxn]; //每个pile[i]是一个vector(仔细理解!)int main() {int a, b;cin >> n;string s1, s2;//4中操作里的两种如 move ontofor(int i = 0; i < n; i++)  pile[i].push_back(i);while(cin >> s1 >> a >> s2 >> b) {int pa, pb, ha, hb;find_block(a, pa, ha);find_block(b, pb, hb);//调用两次函数①if(pa == pb) continue; //非法指令if(s2 == "onto") clear_above(pb, hb);//调用函数②if(s1 == "move") clear_above(pa, ha);pile_onto(pa, ha, pb);//调用函数③}print();//调用函数④return 0;
}

注意观察:变量及其类型,函数及其参数。代码简洁,没有多余{},所以注意函数调用顺序及优先级。
我们发现为何4中操作却只有两个if语句?↓↓↓↓

哦谢特,作者太聪明了!

“上述代码还有一个值得学习的技巧:输入一共有4种指令,但如果完全独立地处理各指令,代码就会变得冗长而且易错。更好的方法是提取出指令之间的共同点,编写函数以减少重复代码。”—聪明的作者

函数①:find_block(a, pa, ha);

//找木块a所在的pile 和height,以引用的形式返回调用者
void find_block(int a, int& p, int& h) {for(p = 0; p < n; p++)for(h = 0; h < pile[p].size(); h++)if(pile[p][h] == a) return;
}

找木块a所在的pile 和height:是指找出a或b的位置
以引用的形式返回调用者:这里的引用是指传进来的参数是直接可操作的。详情百度:c++中引用传递与值传递的区别;

函数② clear_above(pb, hb)

//把第p堆高度为h的木块上方的所有木块移回原位
void clear_above(int p, int h) {
for(int i = h+1; i < pile[p].size(); i++) {int b = pile[p][i];pile[b].push_back(b); //把木块b放回原位
}

函数③ pile_onto(pa, ha, pb);

void pile_onto(int p, int h, int p2) {for(int i = h; i < pile[p].size(); i++)pile[p2].push_back(pile[p][i]);pile[p].resize(h);
}

因为对vector不熟,这里我还有个疑点

pile[p2].push_back(pile[p][i]);

把pile[p][i]添加进pile[p2]中,原元素会消失吗?难道.push_back()这个方法是对数据ctrl+x而不是ctrl+c??(手动滑稽)

函数④

嘿嘿,不解释了,脖子疼。。。

总代码

#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
const int maxn = 30;
int n;
vector<int> pile[maxn]; //每个pile[i]是一个vector
//找木块a所在的pile 和height,以引用的形式返回调用者
void find_block(int a, int& p, int& h) {
for(p = 0; p < n; p++)
for(h = 0; h < pile[p].size(); h++)
if(pile[p][h] == a) return;
}
//把第p堆高度为h的木块上方的所有木块移回原位
void clear_above(int p, int h) {
for(int i = h+1; i < pile[p].size(); i++) {
int b = pile[p][i];
pile[b].push_back(b); //把木块b放回原位
}
pile[p].resize(h+1); //pile 只应保留下标0~h 的元素
}
//把第p堆高度为h及其上方的木块整体移动到p2 堆的顶部
void pile_onto(int p, int h, int p2) {
for(int i = h; i < pile[p].size(); i++)
pile[p2].push_back(pile[p][i]);
pile[p].resize(h);
}
void print() {
for(int i = 0; i < n; i++) {
printf("%d:", i);
for(int j = 0; j < pile[i].size(); j++) printf(" %d", pile[i][j]);
printf("\n");
}
}
int main() {
int a, b;
cin >> n;
string s1, s2;
for(int i = 0; i < n; i++) pile[i].push_back(i);
while(cin >> s1 >> a >> s2 >> b) {
int pa, pb, ha, hb;
find_block(a, pa, ha);
find_block(b, pb, hb);
if(pa == pb) continue; //非法指令
if(s2 == "onto") clear_above(pb, hb);
if(s1 == "move") clear_above(pa, ha);
pile_onto(pa, ha, pb);
}
print();
return 0;
}

小结

数据结构的核心是vectorpile[maxn],所有操作都是围绕它进行的。vector就像一个二维数组,只是第一维的大小是固定的(不超过maxn),但第二维的大小不固定。
vector头文件中的vector是一个不定长数组,可以用clear( )清空,resize( )
改变大小,用push_back( )和pop_back( )在尾部添加和删除元素,用empty( )测试是否为空。
以下是用法。

1.push_back 在数组的最后添加一个数据2.pop_back 去掉数组的最后一个数据3.at 得到编号位置的数据4.begin 得到数组头的指针5.end 得到数组的最后一个单元+1的指针6.front 得到数组头的引用7.back 得到数组的最后一个单元的引用8.max_size 得到vector最大可以是多大9.capacity 当前vector分配的大小10.size 当前使用数据的大小11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值12.reserve 改变当前vecotr所分配空间的大小13.erase 删除指针指向的数据项14.clear 清空当前的vector15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)17.empty 判断vector是否为空18.swap 与另一个vector交换数据

难点及总结

比较难理解的是各个函数体中对vector的操作,对4种指令的抽象总结。
总结:大佬太多,菜鸡我要坚持啊。

本人喜欢批评指正!

有不对的地方一定要告诉我啊!

Uva 101:木块问题 The Blocks Problem(详细说明)+(难点)相关推荐

  1. uva 101 木块问题

    题目大意: 输入n,得到编号为0~n-1的木块,分别摆放在顺序排列编号为0~n-1的位置.现对这些木块进行操作,操作分为四种. 1.move a onto b:把木块a.b上的木块放回各自的原位,再把 ...

  2. the blocks problem(uva 101 or poj 1208)

    题目描述见:uva 101 or poj 1208 关键在于彻底理解题目中搬积木的几个命令的含义,见具体分析 如果还不能理解题意,那么找一个正确通过的代码,编译并输入测试数据,查看其每一个命令的执行情 ...

  3. Uva 101 the block problem 木块问题(算法竞赛经典入门)STL vector

    Uva 101 the block problem 木块问题 题目大意: 输入n,得到编号为0~n-1的木块,分别摆放在顺序排列编号为0~n-1的位置.现对这些木块进行操作,操作分为四种. 1.mov ...

  4. UVa101 - The Blocks Problem

    //UVa101 - The Blocks Problem #include<iostream> #include<cstdio> #include<string> ...

  5. 题解 The Blocks Problem(UVa101)紫书P110vector的应用

    紫书P110:vector的应用:UVa101 The Blocks Problem Vjudge题目地址请移步此处 题目大意: 输入n (0<n<25),得到编号为0到n-1的木块,分别 ...

  6. 《算法竞赛入门经典》 例题5-2 木块问题(The Blocks Problem,UVa 101)

    原题及翻译 Many areas of Computer Science use simple, abstract domains for both analytical and empirical ...

  7. UVA - 101:The Blocks Problem

    原本以为是一道很简单的模拟题,结果写了一个小时...很长时间不碰算法题,的确手感差很多.不过我觉得随着刷题慢慢多起来应该会好的. 题目的意思也有点含糊,需要自己去猜,大概意思就是槽里有一堆木头,每个槽 ...

  8. uva 101 The Blocks Problem

    1.     move a onto b在將a搬到b上之前,先將a和b上的積木放回原來的位置(例如:1就放回1的最開始位罝) 2. move a over b在將a搬到b所在的那堆積木之上之前,先將a ...

  9. 算法竞赛入门经典(第二版) | 例题5-2 木块问题 (紫皮书牛啤!)(UVa101,The Blocks Problem)

    大意: 输入n,代表n个木块,输入最多n种操作类型,按类型对木块进行操作,读入quit结束 输入输出格式: 1.move a onto b:将a和b所在上方的方块先归位,再将a移到b所在柱子 2.mo ...

最新文章

  1. C盘突然爆满怎么办?
  2. mysql 值到99999后不增值了_Mysql 增加新数据,若存在则更新的问题
  3. 【NLP】NLP爱好者学习资源推荐汇总
  4. 数据库更改到Java环境中实现可持续和平
  5. 万字总结!java让字符串反转
  6. CRC16循环冗余校验 RTU-MODBUS标准 Linux C
  7. 征稿 | Call for papers on Knowledge Graphs
  8. CMake使用详解一(单文件编译)
  9. struts2+spring+hibernte整合示例
  10. MATLAB除法运算的精度问题及其解决方案
  11. 想让“贾维斯”成为现实?物联网帮你拥有
  12. 个人博客定制 to 鼠标单击事件绑定
  13. raize控件的安装注意
  14. java espresso_java-Espresso-如何检查是否显示了其中一个视图
  15. AM系列备自投保护装置在广州中山大学附属 第一(南沙)医院配电工程中的应用
  16. 编程中,循环、迭代、遍历和递归之间的区别
  17. mermaid sequenceDiagram使用指南
  18. 人工智能-一种现代的方法 全文总览
  19. 初学者必看!3D建模要学什么软件?
  20. 达梦数据库中的注释的使用

热门文章

  1. java基础加强知识点
  2. tq210 定制linux内核,TQ210 烧写Linux系统
  3. 发电机计算机控制系统的组成,第一章发动机电控系统概述
  4. 英语单词常用词根(二)
  5. 51单片机PWM温控风扇定时关闭手动自动DS18B20测温LCD1602显示
  6. Linq 介绍(一)
  7. 单位公派|消化内科医生赴美国藤校耶鲁大学访学
  8. 把家用计算机改成PLC,怎么把电脑当成plc使用
  9. SpringBoot基础入门篇
  10. OneNET学习资料汇总帖(2018年5月16日)