算法竞赛入门经典(第二版)第3章部分学习实现(上)

时间:2020-11-28 14:10:49
3-1 UVa1585 得分
Sample Input 
5
OOXXOXXOOO
OOXXOOXXOO
OXOXOXOXOXOXOX
OOOOOOOOOO
OOOOXOOOOXOOOOX


Sample Output
10
9
7
55
30
代码如下:
#include <iostream>
#include <string>


using namespace std;


int main()
{
int T(0);
string instr;


cin >> T;
int len(0);
for (int i=0; i<T; i++){
cin >> instr; //getline wrong
len = instr.size();


int num(0), sum(0);
char ch;
for (int j=0; j<len; j++){
ch = instr[j];
if (ch == 'O')
num++;
else
num = 0;
sum += num;
}
cout << sum << endl;
}
return 0;
}
我的感想:
输入的意思是:输入5后,输入一串字符串,马上有结果输出,再输入字符串,又有结果输出,
当输入5个字符串输出结果后时,程序退出。建议一定要在UVaOJ网站上注册提交!!


3-2 UVa1586 分子量

Sample Input 
4
C
C6H5OH
NH2CH2COOH
C12H22O11

Sample Output
12.010
94.108
75.070
342.296
代码如下:
#include <iostream>
#include <string>
#include <iomanip>
#include <stack>


using namespace std;


int main()
{
int T;
cin >> T;


string instr;
int num(0), num0;
char ch;
float seoul_value(0), sum(0);
stack<char> ch_stack;


for (int i=0; i<T; i++){
cin >> instr;
string::iterator it = instr.begin();
while (it != instr.end()){
//cout << "it point to: " << *it << endl;
switch (*it) {
case 'C':
seoul_value = 12.01;
break;
case 'H':
seoul_value = 1.008;
break;
case 'O':
seoul_value = 16.00;
break;
case 'N':
seoul_value = 14.01;
break;
}
//cout << "seoul_value is: " << seoul_value << endl;
char t;
while (1){
t = *(++it);
if (t>='0' && t<='9')
ch_stack.push(t);
else {
it--;
break;
}
}
if (ch_stack.empty())
num = 1;
else {
int tmp = 1;
num = 0; // important
while (!ch_stack.empty()){
ch = ch_stack.top();
num0 = ch - '0';
num += num0 * tmp;
ch_stack.pop();
tmp = tmp * 10;
}
}
sum += num * seoul_value;
it++;
}
cout << setprecision(3) << fixed;
cout << sum << endl;
cout.unsetf(ostream::floatfield);
sum = 0, num = 0;
}
return 0;
}
我的感想:
1 switch case的使用,要有break才行;
2 自加、自减一定要慎用,我觉得应该尽量避免;
3 考虑问题不够全面,比如出现数字12、123的现象;
4 用作局部统计的变量在某次使用完后一定记得置0!在第53行!花了我好长时间排错!
5 如何判断两个字符间的数字,我想到的只有stack、还有更好的办法吗?
6 输入字符'8',输出整数8,直接用字符减去'0'即可,by the way,'0'对应的整数是48;
7 先写伪代码理清思路,很重要啊!


 3-3 UVa1225 数数字

输入一个数n,把前n个整数按12^1112……顺序写在一起,统计1~9分别出现的次数 
#include <iostream>

using namespace std;


//数字较大时要在函数外面声明!
int arr[10000][10] = {};


int main()
{
//对每个数输出组成它的每个数字,存储到数组中
int n, x, y, T;
for (int i=1; i<=10000; ++i){
x = i;
while (x){
y = x % 10;
x = x / 10;
arr[i][y]++;
}
for (int j=0; j<10; ++j)
arr[i][j] += arr[i-1][j];
}


cin >> T;
while (T--){
cin >> n;
for (int i=0; i<9; i++)
cout << arr[n][i] << " ";
cout << arr[n][9];
if (T>0)
cout << endl;
}
return 0;
}

另外:实现了000到100的程序
#include <iostream>

using namespace std;

int main()
{
int a[3] = {};
int n;
for (a[0]=0; a[0]<10;){
for (int i=2; i>=0; i--)
cout << a[i] << " ";
n = 0;
while (a[2] == 0)
if (a[n] == 9)
a[n++] = 0;
else {
a[n]++;
break;
}
cout << endl;
if (a[2] == 1)
break;
}
return 0;
}

// 习题3-4 UVa445 
如果一个字符串可以由某个长度为k的字符串重复多次得到(比如这里的2次),则称该串以k
为周期;输入一个长度不超过80的字符串,输出其最小周期。
input:
abcabcabcabc

output:
3

// 我还没做出来,没有结果输出
程序如下:
#include <iostream>
#include <string>
#include <vector>
#include <queue>


using namespace std;


int main()
{
int t = 1;
cin >> t;


string str;
while (t--){
// process every string
cin >> str;
vector<char> vec1;
queue<char> q2;
vector<char>::size_type size_vec1;
queue<char>::size_type size_q2;
char tmp;
for (string::size_type i=0; i<str.size(); ++i){
if (i==str.size()-1){
cout << "the circle maybe the lenghth of whole string!" << endl;
break;
}


// if diff from vector1[0], vector1.push
if (vec1.empty() || str[i]!=vec1[0]) {
vec1.push_back(str[i]);
continue;
}


// else push to vector2, and compare the coming char
else {
size_vec1 = vec1.size();
for (vector<char>::size_type j=0; j<size_vec1; ++j){
if (str[i] == vec1[j]) {
q2.push(str[i]);
i++ ;
}
else {
while (!q2.empty()){
tmp = q2.front();
vec1.push_back(tmp);
q2.pop();
}
vec1.push_back(str[i]);
break;
}
}
if (q2.size() == size_vec1) {
cout << "the circle is: " << size_vec1 << endl;
break;
}
}
//vec3.clear();
}
vec1.clear();
}
}


3-5 UVa227 谜题
#include <iostream>
#include <vector>


using namespace std;
typedef vector< vector<char> > char_vec;


void getLocate(const char_vec&, int&, int&);
bool moveLocate(char_vec&, int&, int&, char);


int main()
{
char ch[25] = {'T', 'R', 'G', 'S', 'J', 'X', 'D', 'O', 'K', 'L', 'M', ' ', 'V', 'L', 'N', 'W',
'P', 'A', 'B', 'E', 'U', 'Q', 'H', 'C', 'F'};
vector< vector<char> > ch_vec;
ch_vec.resize(5);
for (int i=0; i<5; ++i)
for (int j=0; j<5; ++j)
ch_vec[i].push_back(ch[i*5+j]);
int m, n;
getLocate(ch_vec, m, n);


bool flag(true);
char ch_cin;
while (cin>>ch_cin) {
cout << "m,n= " << m << " " << n << endl;
flag = moveLocate(ch_vec, m, n, ch_cin);
if (flag==false)
break;
}
getLocate(ch_vec, m, n);
cout << "m= " << m << endl;
cout << "n= " << n << endl;


for (int i=0; i<5; ++i) {
for (int j=0; j<5; ++j)
cout << ch_vec[i][j] << " ";
cout << endl;
}
return 0;


}


void getLocate(const char_vec& in_char_vec, int& x, int& y) {
for (int i=0; i<5; ++i)
for (int j=0; j<5; ++j) {
if (in_char_vec[i][j]==' ') {
x = i;
y = j;
}
}
}


bool moveLocate(char_vec& in_char_vec, int& x, int& y, char in_ch) {
char tmp;
if (in_ch=='A') {
if (x==0) {
cerr << "This puzzle has no final configuration." << endl;
return false;
}
else {
tmp = in_char_vec[x][y];
in_char_vec[x][y] = in_char_vec[x-1][y];
in_char_vec[--x][y] = tmp;
return true;
}
}
else if (in_ch=='B') {
if (x==4) {
cerr << "This puzzle has no final configuration." << endl;
return false;
}
else {
tmp = in_char_vec[x][y];
in_char_vec[x][y] = in_char_vec[x+1][y];
in_char_vec[++x][y] = tmp;
return true;
}
}
else if (in_ch=='L') {
if (y==0) {
cerr << "This puzzle has no final configuration." << endl;
return false;
}
else {
tmp = in_char_vec[x][y];
in_char_vec[x][y] = in_char_vec[x][y-1];
in_char_vec[x][--y] = tmp;
return true;
}
}
else if (in_ch=='R') {
if (y==4) {
cerr << "This puzzle has no final configuration." << endl;
return false;
}
else {
tmp = in_char_vec[x][y];
in_char_vec[x][y] = in_char_vec[x][y+1];
in_char_vec[x][++y] = tmp;
return true;
}
}
else {
cout << "to the end!" << endl;
return false;
}
return false;
}