递推/递归与分治策略1

实验题目:王老师爬楼梯

题目描述:
王老师爬楼梯,他可以每次走1级或者2级或者3级楼梯,输入楼梯的级数,求不同的走法数。(要求递推求解)如果N很大,需要高精度计算。
输入要求:
一个整数N,N<=1000。
输出要求:
共有多少种走法。
实验代码

#include <bits/stdc++.h>
using namespace std;class DividedByZeroException {};class BigInteger {
private:vector<char> digits;bool sign;          //  true for positive, false for negitivevoid trim();        //  remove zeros in tail, but if the value is 0, keep only one:)
public:BigInteger(int);    // construct with a int integerBigInteger(string&);BigInteger();BigInteger(const BigInteger&);BigInteger operator=(const BigInteger& op2);BigInteger    abs() const;BigInteger    pow(int a);//binary operatorsfriend BigInteger operator+=(BigInteger&, const BigInteger&);friend BigInteger operator-=(BigInteger&, const BigInteger&);friend BigInteger operator*=(BigInteger&, const BigInteger&);friend BigInteger operator/=(BigInteger&, const BigInteger&) throw(DividedByZeroException);friend BigInteger operator%=(BigInteger&, const BigInteger&) throw(DividedByZeroException);friend BigInteger operator+(const BigInteger&, const BigInteger&);friend BigInteger operator-(const BigInteger&, const BigInteger&);friend BigInteger operator*(const BigInteger&, const BigInteger&);friend BigInteger operator/(const BigInteger&, const BigInteger&) throw(DividedByZeroException);friend BigInteger operator%(const BigInteger&, const BigInteger&) throw(DividedByZeroException);//uniary operatorsfriend BigInteger operator-(const BigInteger&);   //negativefriend BigInteger operator++(BigInteger&);        //++vfriend BigInteger operator++(BigInteger&, int);   //v++friend BigInteger operator--(BigInteger&);        //--vfriend BigInteger operator--(BigInteger&, int);   //v--friend bool operator>(const BigInteger&, const BigInteger&);friend bool operator<(const BigInteger&, const BigInteger&);friend bool operator==(const BigInteger&, const BigInteger&);friend bool operator!=(const BigInteger&, const BigInteger&);friend bool operator>=(const BigInteger&, const BigInteger&);friend bool operator<=(const BigInteger&, const BigInteger&);friend ostream& operator<<(ostream&, const BigInteger&);   //print the BigIntegerfriend istream& operator>>(istream&, BigInteger&);         // input the BigIntegerpublic:static const BigInteger ZERO;static const BigInteger ONE;static const BigInteger TEN;
};
const BigInteger BigInteger::ZERO = BigInteger(0);
const BigInteger BigInteger::ONE = BigInteger(1);
const BigInteger BigInteger::TEN = BigInteger(10);BigInteger::BigInteger() {sign = true;
}BigInteger::BigInteger(int val) { // construct with a int integerif (val >= 0) {sign = true;}else {sign = false;val *= (-1);}do {digits.push_back((char)(val % 10));val /= 10;} while (val != 0);
}BigInteger::BigInteger(string& def) {sign = true;for (string::reverse_iterator iter = def.rbegin(); iter < def.rend(); iter++) {char ch = (*iter);if (iter == def.rend() - 1) {if (ch == '+') {break;}if (ch == '-') {sign = false;break;}}digits.push_back((char)((*iter) - '0'));}trim();
}void BigInteger::trim() {vector<char>::reverse_iterator iter = digits.rbegin();while (!digits.empty() && (*iter) == 0) {digits.pop_back();iter = digits.rbegin();}if (digits.size() == 0) {sign = true;digits.push_back(0);}
}BigInteger::BigInteger(const BigInteger& op2) {sign = op2.sign;digits = op2.digits;
}BigInteger BigInteger::operator=(const BigInteger& op2) {digits = op2.digits;sign = op2.sign;return (*this);
}BigInteger BigInteger::abs() const {if (sign) {return *this;}else {return -(*this);}
}BigInteger BigInteger::pow(int a) {BigInteger res(1);for (int i = 0; i < a; i++) {res *= (*this);}return res;
}//binary operators
BigInteger operator+=(BigInteger& op1, const BigInteger& op2) {if (op1.sign == op2.sign) {     //只处理相同的符号的情况,异号的情况给-处理vector<char>::iterator iter1;vector<char>::const_iterator iter2;iter1 = op1.digits.begin();iter2 = op2.digits.begin();char to_add = 0;        //进位while (iter1 != op1.digits.end() && iter2 != op2.digits.end()) {(*iter1) = (*iter1) + (*iter2) + to_add;to_add = ((*iter1) > 9);    // 大于9进一位(*iter1) = (*iter1) % 10;iter1++;iter2++;}while (iter1 != op1.digits.end()) {    //(*iter1) = (*iter1) + to_add;to_add = ((*iter1) > 9);(*iter1) %= 10;iter1++;}while (iter2 != op2.digits.end()) {char val = (*iter2) + to_add;to_add = (val > 9);val %= 10;op1.digits.push_back(val);iter2++;}if (to_add != 0) {op1.digits.push_back(to_add);}return op1;}else {if (op1.sign) {return op1 -= (-op2);}else {return op1 = op2 - (-op1);}}}BigInteger operator-=(BigInteger& op1, const BigInteger& op2) {if (op1.sign == op2.sign) {     //只处理相同的符号的情况,异号的情况给+处理if (op1.sign) {if (op1 < op2) { // 2 - 3return  op1 = -(op2 - op1);}}else {if (-op1 > -op2) { // (-3)-(-2) = -(3 - 2)return op1 = -((-op1) - (-op2));}else {           // (-2)-(-3) = 3 - 2return op1 = (-op2) - (-op1);}}vector<char>::iterator iter1;vector<char>::const_iterator iter2;iter1 = op1.digits.begin();iter2 = op2.digits.begin();char to_substract = 0;  //借位while (iter1 != op1.digits.end() && iter2 != op2.digits.end()) {(*iter1) = (*iter1) - (*iter2) - to_substract;to_substract = 0;if ((*iter1) < 0) {to_substract = 1;(*iter1) += 10;}iter1++;iter2++;}while (iter1 != op1.digits.end()) {(*iter1) = (*iter1) - to_substract;to_substract = 0;if ((*iter1) < 0) {to_substract = 1;(*iter1) += 10;}else {break;}iter1++;}op1.trim();return op1;}else {if (op1 > BigInteger::ZERO) {return op1 += (-op2);}else {return op1 = -(op2 + (-op1));}}
}
BigInteger operator*=(BigInteger& op1, const BigInteger& op2) {BigInteger result(0);if (op1 == BigInteger::ZERO || op2 == BigInteger::ZERO) {result = BigInteger::ZERO;}else {vector<char>::const_iterator iter2 = op2.digits.begin();while (iter2 != op2.digits.end()) {if (*iter2 != 0) {deque<char> temp(op1.digits.begin(), op1.digits.end());char to_add = 0;deque<char>::iterator iter1 = temp.begin();while (iter1 != temp.end()) {(*iter1) *= (*iter2);(*iter1) += to_add;to_add = (*iter1) / 10;(*iter1) %= 10;iter1++;}if (to_add != 0) {temp.push_back(to_add);}int num_of_zeros = iter2 - op2.digits.begin();while (num_of_zeros--) {temp.push_front(0);}BigInteger temp2;temp2.digits.insert(temp2.digits.end(), temp.begin(), temp.end());temp2.trim();result = result + temp2;}iter2++;}result.sign = ((op1.sign && op2.sign) || (!op1.sign && !op2.sign));}op1 = result;return op1;
}BigInteger operator/=(BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {if (op2 == BigInteger::ZERO) {throw DividedByZeroException();}BigInteger t1 = op1.abs(), t2 = op2.abs();if (t1 < t2) {op1 = BigInteger::ZERO;return op1;}//现在 t1 > t2 > 0//只需将 t1/t2的结果交给result就可以了deque<char> temp;vector<char>::reverse_iterator iter = t1.digits.rbegin();BigInteger temp2(0);while (iter != t1.digits.rend()) {temp2 = temp2 * BigInteger::TEN + BigInteger((int)(*iter));char s = 0;while (temp2 >= t2) {temp2 = temp2 - t2;s = s + 1;}temp.push_front(s);iter++;}op1.digits.clear();op1.digits.insert(op1.digits.end(), temp.begin(), temp.end());op1.trim();op1.sign = ((op1.sign && op2.sign) || (!op1.sign && !op2.sign));return op1;
}BigInteger operator%=(BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {return op1 -= ((op1 / op2) * op2);
}BigInteger operator+(const BigInteger& op1, const BigInteger& op2) {BigInteger temp(op1);temp += op2;return temp;
}
BigInteger operator-(const BigInteger& op1, const BigInteger& op2) {BigInteger temp(op1);temp -= op2;return temp;
}BigInteger operator*(const BigInteger& op1, const BigInteger& op2) {BigInteger temp(op1);temp *= op2;return temp;}BigInteger operator/(const BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {BigInteger temp(op1);temp /= op2;return temp;
}BigInteger operator%(const BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {BigInteger temp(op1);temp %= op2;return temp;
}//uniary operators
BigInteger operator-(const BigInteger& op) {  //negativeBigInteger temp = BigInteger(op);temp.sign = !temp.sign;return temp;
}BigInteger operator++(BigInteger& op) {   //++vop += BigInteger::ONE;return op;
}BigInteger operator++(BigInteger& op, int x) { //v++BigInteger temp(op);++op;return temp;
}BigInteger operator--(BigInteger& op) {   //--vop -= BigInteger::ONE;return op;
}BigInteger operator--(BigInteger& op, int x) { //v--BigInteger temp(op);--op;return temp;
}bool operator<(const BigInteger& op1, const BigInteger& op2) {if (op1.sign != op2.sign) {return !op1.sign;}else {if (op1.digits.size() != op2.digits.size())return (op1.sign && op1.digits.size() < op2.digits.size())|| (!op1.sign && op1.digits.size() > op2.digits.size());vector<char>::const_reverse_iterator iter1, iter2;iter1 = op1.digits.rbegin();iter2 = op2.digits.rbegin();while (iter1 != op1.digits.rend()) {if (op1.sign && *iter1 < *iter2) {return true;}if (op1.sign && *iter1 > *iter2) {return false;}if (!op1.sign && *iter1 > *iter2) {return true;}if (!op1.sign && *iter1 < *iter2) {return false;}iter1++;iter2++;}return false;}
}
bool operator==(const BigInteger& op1, const BigInteger& op2) {if (op1.sign != op2.sign || op1.digits.size() != op2.digits.size()) {return false;}vector<char>::const_iterator iter1, iter2;iter1 = op1.digits.begin();iter2 = op2.digits.begin();while (iter1 != op1.digits.end()) {if (*iter1 != *iter2) {return false;}iter1++;iter2++;}return true;
}bool operator!=(const BigInteger& op1, const BigInteger& op2) {return !(op1 == op2);
}bool operator>=(const BigInteger& op1, const BigInteger& op2) {return (op1 > op2) || (op1 == op2);
}bool operator<=(const BigInteger& op1, const BigInteger& op2) {return (op1 < op2) || (op1 == op2);
}bool operator>(const BigInteger& op1, const BigInteger& op2) {return !(op1 <= op2);
}ostream& operator<<(ostream& stream, const BigInteger& val) {  //print the BigIntegerif (!val.sign) {stream << "-";}for (vector<char>::const_reverse_iterator iter = val.digits.rbegin(); iter != val.digits.rend(); iter++) {stream << (char)((*iter) + '0');}return stream;
}istream& operator>>(istream& stream, BigInteger& val) {   //Input the BigIntegerstring str;stream >> str;val = BigInteger(str);return stream;
}
bool flag[1001] = { false };
BigInteger num[1001];
BigInteger f(int n)
{if (n == 0){if (flag[n])return num[n];else{flag[n] = true;num[n] = 1;return num[n];}}else if (n == 1){if (flag[n])return num[n];else{flag[n] = true;num[n] = 1;return num[n];}}else if (n == 2){if (flag[n])return num[n];else{flag[n] = true;num[n] = 2;return num[n];}}else {if (flag[n]){return num[n];}else{num[n] = f(n - 1) + f(n - 2) + f(n - 3);flag[n] = true;return num[n];}}
}int main() {BigInteger res;int n;cin >> n;res = f(n);cout << res << endl;return 0;
}

算法分析与知识点:
本题主要涉及大数运算以及递归的应用,递归需要分析递归的条件,本题的递归条件为考虑王老师最后一次跨几步可分为最后跨一步、最后跨两步和最后跨三步三种得出
f ( n ) = f ( n − 1 ) + f ( n − 2 ) + f ( n − 3 ) f\left( n \right) =f\left( n-1 \right) +f\left( n-2 \right) +f\left( n-3 \right) f(n)=f(n−1)+f(n−2)+f(n−3)

实验题目:铺砖

题目描述:
对于一个2行N列的走道。现在用12或22的砖去铺满。问有多少种不同的方式(请用递推方式求解)。如果N很大,需要高精度计算。下图是一个2行17列的走道的某种铺法:

输入要求:
一个整数N,N<=1000。
输出要求:
共有多少种铺法。
实验代码

#include <bits/stdc++.h>
using namespace std;class DividedByZeroException {};class BigInteger {
private:vector<char> digits;bool sign;          //  true for positive, false for negitivevoid trim();        //  remove zeros in tail, but if the value is 0, keep only one:)
public:BigInteger(int);    // construct with a int integerBigInteger(string&);BigInteger();BigInteger(const BigInteger&);BigInteger operator=(const BigInteger& op2);BigInteger    abs() const;BigInteger    pow(int a);//binary operatorsfriend BigInteger operator+=(BigInteger&, const BigInteger&);friend BigInteger operator-=(BigInteger&, const BigInteger&);friend BigInteger operator*=(BigInteger&, const BigInteger&);friend BigInteger operator/=(BigInteger&, const BigInteger&) throw(DividedByZeroException);friend BigInteger operator%=(BigInteger&, const BigInteger&) throw(DividedByZeroException);friend BigInteger operator+(const BigInteger&, const BigInteger&);friend BigInteger operator-(const BigInteger&, const BigInteger&);friend BigInteger operator*(const BigInteger&, const BigInteger&);friend BigInteger operator/(const BigInteger&, const BigInteger&) throw(DividedByZeroException);friend BigInteger operator%(const BigInteger&, const BigInteger&) throw(DividedByZeroException);//uniary operatorsfriend BigInteger operator-(const BigInteger&);   //negativefriend BigInteger operator++(BigInteger&);        //++vfriend BigInteger operator++(BigInteger&, int);   //v++friend BigInteger operator--(BigInteger&);        //--vfriend BigInteger operator--(BigInteger&, int);   //v--friend bool operator>(const BigInteger&, const BigInteger&);friend bool operator<(const BigInteger&, const BigInteger&);friend bool operator==(const BigInteger&, const BigInteger&);friend bool operator!=(const BigInteger&, const BigInteger&);friend bool operator>=(const BigInteger&, const BigInteger&);friend bool operator<=(const BigInteger&, const BigInteger&);friend ostream& operator<<(ostream&, const BigInteger&);   //print the BigIntegerfriend istream& operator>>(istream&, BigInteger&);         // input the BigIntegerpublic:static const BigInteger ZERO;static const BigInteger ONE;static const BigInteger TEN;
};
const BigInteger BigInteger::ZERO = BigInteger(0);
const BigInteger BigInteger::ONE = BigInteger(1);
const BigInteger BigInteger::TEN = BigInteger(10);BigInteger::BigInteger() {sign = true;
}BigInteger::BigInteger(int val) { // construct with a int integerif (val >= 0) {sign = true;}else {sign = false;val *= (-1);}do {digits.push_back((char)(val % 10));val /= 10;} while (val != 0);
}BigInteger::BigInteger(string& def) {sign = true;for (string::reverse_iterator iter = def.rbegin(); iter < def.rend(); iter++) {char ch = (*iter);if (iter == def.rend() - 1) {if (ch == '+') {break;}if (ch == '-') {sign = false;break;}}digits.push_back((char)((*iter) - '0'));}trim();
}void BigInteger::trim() {vector<char>::reverse_iterator iter = digits.rbegin();while (!digits.empty() && (*iter) == 0) {digits.pop_back();iter = digits.rbegin();}if (digits.size() == 0) {sign = true;digits.push_back(0);}
}BigInteger::BigInteger(const BigInteger& op2) {sign = op2.sign;digits = op2.digits;
}BigInteger BigInteger::operator=(const BigInteger& op2) {digits = op2.digits;sign = op2.sign;return (*this);
}BigInteger BigInteger::abs() const {if (sign) {return *this;}else {return -(*this);}
}BigInteger BigInteger::pow(int a) {BigInteger res(1);for (int i = 0; i < a; i++) {res *= (*this);}return res;
}//binary operators
BigInteger operator+=(BigInteger& op1, const BigInteger& op2) {if (op1.sign == op2.sign) {     //只处理相同的符号的情况,异号的情况给-处理vector<char>::iterator iter1;vector<char>::const_iterator iter2;iter1 = op1.digits.begin();iter2 = op2.digits.begin();char to_add = 0;        //进位while (iter1 != op1.digits.end() && iter2 != op2.digits.end()) {(*iter1) = (*iter1) + (*iter2) + to_add;to_add = ((*iter1) > 9);    // 大于9进一位(*iter1) = (*iter1) % 10;iter1++;iter2++;}while (iter1 != op1.digits.end()) {    //(*iter1) = (*iter1) + to_add;to_add = ((*iter1) > 9);(*iter1) %= 10;iter1++;}while (iter2 != op2.digits.end()) {char val = (*iter2) + to_add;to_add = (val > 9);val %= 10;op1.digits.push_back(val);iter2++;}if (to_add != 0) {op1.digits.push_back(to_add);}return op1;}else {if (op1.sign) {return op1 -= (-op2);}else {return op1 = op2 - (-op1);}}}BigInteger operator-=(BigInteger& op1, const BigInteger& op2) {if (op1.sign == op2.sign) {     //只处理相同的符号的情况,异号的情况给+处理if (op1.sign) {if (op1 < op2) { // 2 - 3return  op1 = -(op2 - op1);}}else {if (-op1 > -op2) { // (-3)-(-2) = -(3 - 2)return op1 = -((-op1) - (-op2));}else {           // (-2)-(-3) = 3 - 2return op1 = (-op2) - (-op1);}}vector<char>::iterator iter1;vector<char>::const_iterator iter2;iter1 = op1.digits.begin();iter2 = op2.digits.begin();char to_substract = 0;  //借位while (iter1 != op1.digits.end() && iter2 != op2.digits.end()) {(*iter1) = (*iter1) - (*iter2) - to_substract;to_substract = 0;if ((*iter1) < 0) {to_substract = 1;(*iter1) += 10;}iter1++;iter2++;}while (iter1 != op1.digits.end()) {(*iter1) = (*iter1) - to_substract;to_substract = 0;if ((*iter1) < 0) {to_substract = 1;(*iter1) += 10;}else {break;}iter1++;}op1.trim();return op1;}else {if (op1 > BigInteger::ZERO) {return op1 += (-op2);}else {return op1 = -(op2 + (-op1));}}
}
BigInteger operator*=(BigInteger& op1, const BigInteger& op2) {BigInteger result(0);if (op1 == BigInteger::ZERO || op2 == BigInteger::ZERO) {result = BigInteger::ZERO;}else {vector<char>::const_iterator iter2 = op2.digits.begin();while (iter2 != op2.digits.end()) {if (*iter2 != 0) {deque<char> temp(op1.digits.begin(), op1.digits.end());char to_add = 0;deque<char>::iterator iter1 = temp.begin();while (iter1 != temp.end()) {(*iter1) *= (*iter2);(*iter1) += to_add;to_add = (*iter1) / 10;(*iter1) %= 10;iter1++;}if (to_add != 0) {temp.push_back(to_add);}int num_of_zeros = iter2 - op2.digits.begin();while (num_of_zeros--) {temp.push_front(0);}BigInteger temp2;temp2.digits.insert(temp2.digits.end(), temp.begin(), temp.end());temp2.trim();result = result + temp2;}iter2++;}result.sign = ((op1.sign && op2.sign) || (!op1.sign && !op2.sign));}op1 = result;return op1;
}BigInteger operator/=(BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {if (op2 == BigInteger::ZERO) {throw DividedByZeroException();}BigInteger t1 = op1.abs(), t2 = op2.abs();if (t1 < t2) {op1 = BigInteger::ZERO;return op1;}//现在 t1 > t2 > 0//只需将 t1/t2的结果交给result就可以了deque<char> temp;vector<char>::reverse_iterator iter = t1.digits.rbegin();BigInteger temp2(0);while (iter != t1.digits.rend()) {temp2 = temp2 * BigInteger::TEN + BigInteger((int)(*iter));char s = 0;while (temp2 >= t2) {temp2 = temp2 - t2;s = s + 1;}temp.push_front(s);iter++;}op1.digits.clear();op1.digits.insert(op1.digits.end(), temp.begin(), temp.end());op1.trim();op1.sign = ((op1.sign && op2.sign) || (!op1.sign && !op2.sign));return op1;
}BigInteger operator%=(BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {return op1 -= ((op1 / op2) * op2);
}BigInteger operator+(const BigInteger& op1, const BigInteger& op2) {BigInteger temp(op1);temp += op2;return temp;
}
BigInteger operator-(const BigInteger& op1, const BigInteger& op2) {BigInteger temp(op1);temp -= op2;return temp;
}BigInteger operator*(const BigInteger& op1, const BigInteger& op2) {BigInteger temp(op1);temp *= op2;return temp;}BigInteger operator/(const BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {BigInteger temp(op1);temp /= op2;return temp;
}BigInteger operator%(const BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) {BigInteger temp(op1);temp %= op2;return temp;
}//uniary operators
BigInteger operator-(const BigInteger& op) {  //negativeBigInteger temp = BigInteger(op);temp.sign = !temp.sign;return temp;
}BigInteger operator++(BigInteger& op) {   //++vop += BigInteger::ONE;return op;
}BigInteger operator++(BigInteger& op, int x) { //v++BigInteger temp(op);++op;return temp;
}BigInteger operator--(BigInteger& op) {   //--vop -= BigInteger::ONE;return op;
}BigInteger operator--(BigInteger& op, int x) { //v--BigInteger temp(op);--op;return temp;
}bool operator<(const BigInteger& op1, const BigInteger& op2) {if (op1.sign != op2.sign) {return !op1.sign;}else {if (op1.digits.size() != op2.digits.size())return (op1.sign && op1.digits.size() < op2.digits.size())|| (!op1.sign && op1.digits.size() > op2.digits.size());vector<char>::const_reverse_iterator iter1, iter2;iter1 = op1.digits.rbegin();iter2 = op2.digits.rbegin();while (iter1 != op1.digits.rend()) {if (op1.sign && *iter1 < *iter2) {return true;}if (op1.sign && *iter1 > *iter2) {return false;}if (!op1.sign && *iter1 > *iter2) {return true;}if (!op1.sign && *iter1 < *iter2) {return false;}iter1++;iter2++;}return false;}
}
bool operator==(const BigInteger& op1, const BigInteger& op2) {if (op1.sign != op2.sign || op1.digits.size() != op2.digits.size()) {return false;}vector<char>::const_iterator iter1, iter2;iter1 = op1.digits.begin();iter2 = op2.digits.begin();while (iter1 != op1.digits.end()) {if (*iter1 != *iter2) {return false;}iter1++;iter2++;}return true;
}bool operator!=(const BigInteger& op1, const BigInteger& op2) {return !(op1 == op2);
}bool operator>=(const BigInteger& op1, const BigInteger& op2) {return (op1 > op2) || (op1 == op2);
}bool operator<=(const BigInteger& op1, const BigInteger& op2) {return (op1 < op2) || (op1 == op2);
}bool operator>(const BigInteger& op1, const BigInteger& op2) {return !(op1 <= op2);
}ostream& operator<<(ostream& stream, const BigInteger& val) {  //print the BigIntegerif (!val.sign) {stream << "-";}for (vector<char>::const_reverse_iterator iter = val.digits.rbegin(); iter != val.digits.rend(); iter++) {stream << (char)((*iter) + '0');}return stream;
}istream& operator>>(istream& stream, BigInteger& val) {   //Input the BigIntegerstring str;stream >> str;val = BigInteger(str);return stream;
}
bool flag[1001] = { false };
BigInteger num[1001];
BigInteger f(int n)
{if (n == 1){if (flag[n])return num[n];else{flag[n] = true;num[n] = 1;//cout << n << endl;return num[n];}}else if (n == 2){if (flag[n])return num[n];else{flag[n] = true;num[n] = 3;//cout << n << endl;return num[n];}}else {if (flag[n]){return num[n];}else{num[n] = f(n - 1) + f(n - 2) + f(n - 2);flag[n] = true;//cout << n << endl;return num[n];}}
}int main() {BigInteger res;int n;cin >> n;res = f(n);cout << res << endl;return 0;
}

算法分析与知识点:

本题主要涉及大数运算以及递归的应用,递归需要分析递归的条件,本题的递归条件为考虑铺砖最后一次剩几列可分为最后剩一列和最后剩两列两种,剩两列又可分为22和2个12,最终得出 n u m [ n ] = f ( n − 1 ) + f ( n − 2 ) + f ( n − 2 ) num\left[ n \right] =f\left( n-1 \right) +f\left( n-2 \right) +f\left( n-2 \right) num[n]=f(n−1)+f(n−2)+f(n−2)

递推/递归与分治策略2

实验题目:第K小的数

题目描述:
输入n个数,求其中第k小的数。(要求采用分治法完成,不建议采用完整的排序)
输入要求:
第一行包含两个整数n和k;n<1000,1<=K<=n
第二行包含n个整数。

输出要求:
输出第k小的那个整数。

实验代码

#include <bits/stdc++.h>
using namespace std;int f(vector<int> data, int k) {int pop_size = data.size();if (pop_size < 75) {sort(data.begin(), data.end());return data[k - 1];}vector<int> middle;int group_num = 5;for (int i = 0;i < pop_size;i += group_num) {vector<int> temp;for (int j = i;j < i + group_num && j < pop_size;j++) {temp.push_back(data[j]);}if (temp.size())middle.push_back(f(temp, 1 + temp.size() / 2));}int key = f(middle, 1 + middle.size() / 2);vector<int> part1, part2;for (int i = 0;i < pop_size;i++) {if (data[i] > key)part1.push_back(data[i]);elsepart2.push_back(data[i]);}if (k <= part2.size())return f(part2, k);elsereturn f(part1, k - part2.size());
}
int main() {vector<int> data;int n, k;cin >> n >> k;for (int i = 0;i < n;i++) {int t;cin >> t;data.push_back(t);}int ans = f(data, k);cout << ans << endl;return 0;
}

算法分析与知识点:
本题主要运用了递归分治的思想,将原问题转化为先求5个数一组的小组分别求出其中位数,最后汇总得到总数组的中位数,然后根据该数的下标与k的关系,转化为规模为原问题一半的子问题。

实验题目:涂格子

题目描述:
有排成一行的n个方格,用红、粉、绿三色涂每个格子,要求:
(1)任何相邻的方格不能同色;
(2)且首尾两格也不同色
求n个格子满足要求的涂法数。

输入要求:
输入多个整数n,每个整数表示有多少个方格,n<=60
输出要求:
输出多个整数,一行一个,表示每个对应输入的涂法数
实验代码

#include <bits/stdc++.h>
using namespace std;
long long f(int n) {long long data[61] = { 3,6,6 };if (n <= 2)return data[n - 1];else{for (int i = 3;i < n;i++) {data[i] = data[i - 1] + 2 * data[i - 2];//递推公式}return data[n - 1];}
}
int main() {int n;while (cin >> n) {long long  ans = f(n);cout << ans << endl;}return 0;
}

算法分析与知识点:
本题主要运用递归的思想,考虑倒数第二个格子与第一个格子的颜色是否相同可分为两种情况,进一步分析可得到以下关系 d a t a [ i ] = d a t a [ i − 1 ] + 2 ∗ d a t a [ i − 2 ] data\left[ i \right] =data\left[ i-1 \right] +2*data\left[ i-2 \right] data[i]=data[i−1]+2∗data[i−2]

实验题目:过河卒/noip2002

题目描述:
棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下或向右。同时在棋盘上的任一点有一个对方的马(如图中的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点。例如图中C点上的马可以控制9个点。卒不能走到对方马的控制点。
棋盘用坐标表示,A点坐标(0,0)、B点坐标(n, m) (n,m为不超过20的整数,并由键盘输入),同样马的位置坐标C是需要给出的(C≠A,且C≠B)。现在要求你计算出卒从A点能够到达B点的路径条数。

输入要求:
B点的坐标(n, m)以及对方马的坐标(x,y),不用判错。
输出要求:
一个整数(路径的条数)
实验代码

#include <bits/stdc++.h>
using namespace std;
bool check(int cx, int cy, int x, int y) {//检查位置是否为马的控制点if (abs(cx - x) * abs(cy - y) == 2 || (cx == x && cy == y))return true;elsereturn false;
}
long long f(int cx,int cy, int n, int m, int x, int y) {long long map[21][21] = { 0 };for (int i = 0;i <= n;i++) {for (int j = 0;j <= m;j++) {if (i == 0 && j == 0)map[i][j] = 1;else if (i == 0){if (check(0, j, x, y))map[0][j] = 0;elsemap[0][j] = map[0][j - 1];}else if (j == 0){if (check(i, 0, x, y))map[i][0] = 0;elsemap[i][0] = map[i - 1][0];}else {if (check(i, j, x, y))map[i][j] = 0;elsemap[i][j] = map[i - 1][j] + map[i][j - 1];}}}return map[n][m];
}
int main() {int m, n, x, y;cin >> m>> n >> x >> y;long long ans = f(0, 0, m, n, x, y);cout << ans << endl;return 0;
}

算法分析与知识点:

本题主要采用动态规划的思想来求解,若用递归的方式来求解会导致超时的结果。根据题目分析可得我们令边界都为1,可以写出个状态方程 m a p [ i ] [ j ] = m a p [ i − 1 ] [ j ] + m a p [ i ] [ j − 1 ] map\left[ i \right] \left[ j \right] =map\left[ i-1 \right] \left[ j \right] +map\left[ i \right] \left[ j-1 \right] map[i][j]=map[i−1][j]+map[i][j−1] 有了这个公式就好办了。

递推/递归与分治策略-堂练

实验题目:装错信封

题目描述:
组合学中有这样一个问题:某人给五个朋友写信,邀请他们来家中聚会。请柬和信封交由助手去处理。粗心的助手却把请柬全装错了信封。请问:助手会有多少种装错的可能呢?
这个问题是是由当时有名的数学家约翰·伯努利(Johann Bernoulli,1667—1748)的儿子
丹尼尔·伯努利(Danid Bernoulli,17OO一1782)提出来的。

输入要求:
输入数据包含多个多个测试实例,每个测试实例占用一行,每行包含一个正整数n(1<n<=10),n表示朋友的人数。
输出要求:
对于每行输入请输出可能的错误方式的数量,每个实例的输出占用一行。
实验代码

#include <bits/stdc++.h>
using namespace std;
int f(int n) { //f函数求装错信封的可能性if (n == 1)//递归边界return 0;else if (n == 2)//递归边界return 1;return (n - 1) * (f(n - 1) + f(n - 2)); //递归条件
}int main() {int n;while (cin >> n) {int ans = f(n);cout << ans << endl;}return 0;
}

算法分析与知识点:
本题主要涉及递归分治的思想先任意指定一封,看它与剩余n-1封信的组合情况可分为它与第i封交叉犯错和没有与其发生交叉犯错,可列出状态转移方程
f ( n ) = ( n − 1 ) ∗ ( f ( n − 1 ) + f ( n − 2 ) ) f\left( n \right) =\left( n-1 \right) *\left( f\left( n-1 \right) +f\left( n-2 \right) \right) f(n)=(n−1)∗(f(n−1)+f(n−2))

实验题目:假币比真币轻

题目描述:
在n枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,已知道假币比真币轻。可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测这枚假币。要求用分治法称重来实现。
输入要求:
第1行输入一个整数n(2<=n<=100),表示有n个硬币。
第2还开始输入n个整数,表示每个硬币的重量。

输出要求:
输出一个整数(1…n),表示假币是第几个硬币。
实验代码

#include <bits/stdc++.h>
using namespace std;
int f(int coin[], int left, int right) {//f函数求假硬币的位置if (left == right)//递归边界,返回假硬币的位置return left;int middle = (left + right) / 2;//将硬币分成两堆int sum1 = 0, sum2 = 0;//记录两堆硬币的总重量for (int i = left;i <= middle;i++) {sum1 += coin[i];}for (int i = middle + 1;i <= right;i++) {sum2 += coin[i];}if (sum1 / (middle - left + 1) > sum2 / (right - middle)) //根据平均重量来判断假硬币在哪一堆return f(coin, middle + 1, right);elsereturn f(coin, left, middle);return 0;
}
int main() {int n;int coin[101];cin >> n;for (int i = 0;i < n;i++) {cin >> coin[i];}int ans = f(coin, 0, n - 1);cout << ans + 1 << endl;return 0;
}

算法分析与知识点:
本题主要涉及递归分治,将原问题的解分解为若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,也无需对子问题进行合并。这样每进行一次分治问题的规模就减小了一半,便于求解。

实验题目: 棋盘覆盖

题目描述:
在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

输入要求:
输入一个整数k,k<=5;
输入特殊格子的坐标x,y。

输出要求:
输出一个由数值表示的二维矩阵。填充规则如下:
(1)用数值填充方格;
(2)特殊方格数值为0;
(3)从中心点开始;然后左上、右上、左下、右下的计数顺序填数;同一块用相同数值表示;
(4)每个数值占4个位置空间;右对齐,左补空格。

实验代码

#include <bits/stdc++.h>
using namespace std;
int def[101][101] = { 0 };
static int t = 0;void chess(int a, int b, int aa, int bb, int length) {//a,b为子棋盘左上角坐标,aa,bb为特殊点坐标,length为子棋盘长度if (length == 1) {return;}t++;int tem = t;int l = length / 2;if (aa < a + l && bb < b + l) { //特殊点在左上的正方形中chess(a, b, aa, bb, l);}else {def[a + l - 1][b + l - 1] = tem;//cout<<"左上  "<<l<<"  "<<l<<"  "<<def[l][l]<<endl;chess(a, b, a + l - 1, b + l - 1, l);}if (aa < a + l && bb >= b + l) {//右上角的子棋盘chess(a, b + l, aa, bb, l);}else {def[a + l - 1][b + l] = tem;//cout<<"右上  "<<a+l-1<<"  "<<b+l<<"  "<<def[a+l][b+l-1]<<endl;chess(a, b + l, a + l - 1, b + l, l);}if (aa >= a + l && bb < b + l) {//左下角的子棋盘chess(a + l, b, aa, bb, l);}else {def[a + l][b + l - 1] = tem;//cout<<"左下  "<<a+l<<" "<<b+l-1<<"  "<<def[a+l-1][b+l]<<endl;chess(a + l, b, a + l, b + l - 1, l);}if (aa >= a + l && bb >= b + l) {//右下角的子棋盘chess(a + l, b + l, aa, bb, l);}else {def[a + l][b + l] = tem;//cout<<"右下  "<<a+l<<"  "<<b+l<<"  "<<def[a+l][b+l]<<endl;chess(a + l, b + l, a + l, b + l, l);}
}
int main() {int n, a, b, aa, bb, length, m;//a,b是子棋盘左上角的行号和列号//aa,bb是特殊点的行号和列号int k, x, y;cin >> k >> x >> y;length = int(pow(2, k));aa = x + 1;bb = y + 1;a = b = 1;m = length;chess(a, b, aa, bb, length);for (int i = 1;i <= m;i++) { //输出结果for (int j = 1;j <= m;j++) {printf("%4d", def[i][j]);if (j == m) {cout << endl;}}}return 0;
}

算法分析与知识点:
本题主要涉及递归分治的思想,当k>0时,将2k*2k棋盘分割为4个2k-1*2k-1子棋盘,如图

特殊方格必定位于这四个小棋盘中,其余三个子棋盘没有特殊方格,为了将这三个无特殊方格的子棋盘转换为特殊棋盘,我们可以用一个L型骨盘覆盖这三个较小棋盘的会合处,如图所示
从图上可以看出,这三个子棋盘上被L型骨牌覆盖的方格就成为该棋盘上的特殊方格,从而将问题分解为4个较小规模的棋盘覆盖问题。递归地使用这种分割方法,直至棋盘简化为1*1棋盘,就结束递归。

算法实验一 递归与分治策略相关推荐

  1. 算法设计与分析第2章 递归与分治策略

    第2章 递归与分治策略 2.1 递归算法 递归算法:直接或间接地调用自身的算法. 递归函数:用函数自身给出定义的函数.两个要素:边界条件.递归方程 优点:结构清晰,可读性强,而且容易用数学归纳法来证明 ...

  2. 计算机算法设计与分析之----- 递归与分治策略

    递归与分治策略 [Master定理] 快速排序 优化 逆序对(归并算法) 火柴排队[NOIP2013 提高组] 集合求和 方法一: 递归 (2^n ) 方法二: 组合数学知识 [HNOI2008]越狱 ...

  3. 算法设计与分析——递归与分治策略——全排列

    算法设计与分析--递归与分治策略--全排列 全排列问题的解决是通过分治与递归思想来解决的 首先判断是否递归到了最后一位,如果递归到了最后一位,则输出他当前的全排列序列. 如果没有到达最后一位,则循环的 ...

  4. c语言分治法求众数重数_五大常见算法策略之——递归与分治策略

    递归与分治策略 递归与分治策略是五大常见算法策略之一,分治策略的思想就是 分而治之 ,即先将一个规模较大的大问题分解成若干个规模较小的小问题,再对这些小问题进行解决,得到的解,在将其组合起来得到最终的 ...

  5. 分治法一个整数数列求最大值最小值_五大常见算法策略之丨递归与分治策略

    递归与分治策略 递归与分治策略是五大常见算法策略之一,分治策略的思想就是分而治之,即先将一个规模较大的大问题分解成若干个规模较小的小问题,再对这些小问题进行解决,得到的解,在将其组合起来得到最终的解. ...

  6. 递归与分治策略算法之循环赛日程表

    递归与分治策略算法之循环赛日程表 1.先简单的来介绍一下分治策略的思想 分治策略的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,分解出来的子问题与原问题相同,并且相互独立.通过递归去解决子 ...

  7. ​相似算法比较:递归、分治、动态规划、贪心、回溯、分支限界​

    相似算法比较:递归.分治.动态规划.贪心.回溯.分支限界 ​ 在学习算法的过程中,递归.分治.动态规划.贪心.回溯.分支限界这些算法有些类似,都是为了解决大问题,都是把大问题拆分成小问题来解决,但她们 ...

  8. 递归与分治java策略实验报告_递归与分治策略–计算机算法设计与分析

    递归概念:直接或者间接调用自身的算法,称为递归运算. 分治思想:把一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相等,递归解决子问题后再将结果合并 下方为一些应用函数.因为 ...

  9. 算法设计与分析——递归与分治策略——最接近点对问题

    [问题描述] 最近对问题要求在包含有n个点的集合S中,找出距离最近的两个点.设 p1(x1,y1),p2(x2,y2),--,pn(xn,yn)是平面的n个点. 严格地将,最近点对可能不止一对,此例输 ...

最新文章

  1. JavaEE Tutorials (15) - 对Java持久化API应用使用二级缓存
  2. matlab while循环
  3. php引用计数的基本知识
  4. Nginx负载均衡、ssl原理,生成ssl密钥对,配置Nginxssl
  5. laravel使用migrate操作数据库迁移
  6. Windows phone 8 是新的起点吗?
  7. 异步生成器_异步生成器作为状态管理的替代方法
  8. 坦克乘员协同训练模拟系统
  9. Git和Github详细入门教程
  10. java图片压缩工具
  11. 笨方法学python3 习题41
  12. 三菱plc可以用c语言编程吗,三菱PLC六种常用编程语言讲解
  13. cmd运行jar时提示没有主类清单属性或找不到主类
  14. 企业使用防伪税控开票子系统出现问题常见问题
  15. 中国SaaS驶入「2.0时代」
  16. 大数据周周看:金融科技公司融360赴美IPO,小蓝单车人去楼空,用户押金退还困难
  17. 阿尔茨海默病最新研究进展(2021年)
  18. 韩国顶级舞台剧《爱上街舞少年的芭蕾少女》掀起街舞狂潮
  19. 券商API/程序化交易接口
  20. Matlab广义追赶法(Thomas法)

热门文章

  1. 冒泡排序算法(java)
  2. 用友U8之MRP计划 专栏目录
  3. 为什么企鹅Tux是Linux的吉祥物?
  4. nz-zorror table不显示 “暂无数据”
  5. 599就能照靓你的美!年轻就该放纵自High
  6. linux下如何挂载usb设备,Linux下挂载USB盘
  7. OSChina 周一乱弹 —— 先扒龙王庙 再用大炮轰你
  8. docker镜像的版本(bullseye、buster、slim、alphine)
  9. linux getopt命令,shell脚本之getopt命令
  10. GC8548双通道H桥电机驱动芯片