股民解套问题
某股民投资某证券,购入该证券时间作为起始点0,当天的盈亏也定为0。假定证券价格每个交易日的变化有三档:比前一个交易日上涨1个单位,与前一个交易日持平,比前一个交易日下跌1个单位。
该股民对其持有证券的收益期望值是k个单位。即:只要该证券的价格比其购入的价格高k个单位,他就会卖出该证券获利了结,反之如果没有达到预期的利润,他就会继续持有该证券,持有的天数最多为N个交易日。在第N个交易日,股民已经失去了耐心,无论是否达到收益预期,证券都会被该股民卖出。
第一问
请根据已经学过的算法策略,在屏幕输出从证券购买日开始,能使该股民在第N以及第N个交易日以内获利k个单位的证券每日价格走势组合,并统计符合条件的价格走势总数。
第二问
要求用2种算法策略实现。
例
当N=3,k=1时,表示最多持有3个交易日,获利1个单位即了结。
输入:
3 1
屏幕输出结果为:
1
0 1
0 0 1
-1 1 1
count=4
解答
分治法
#include <cstring>
#include <iostream>
using namespace std;
int paths = 0;
int bfs(int days, int expected, int value, string path) {
if (days < 0) return 0;
if (value == expected) {
paths++;
std::cout << path << endl;
return 0;
}
else {
bfs(days - 1, expected, value + 1, path + " 1 ");
bfs(days - 1, expected, value + 0, path + " 0 ");
bfs(days - 1, expected, value - 1, path + "-1 ");
}
}
int main() {
int days = 0;
int expected = 0;
std::cin >> days >> expected;
bfs(days, expected, 0, "");
std::cout << "counts=" << paths << endl;
return 0;
}
思路
根据树形结构直接采用分治法递归遍历
测试
输入 “3 1”
3 1
1
0 1
0 0 1
-1 1 1
counts=4
--------------------------------
Process exited after 5.928 seconds with return value 0
请按任意键继续. . .
输入"4 2"
4 2
1 1
1 0 1
1 0 0 1
1 -1 1 1
0 1 1
0 1 0 1
0 0 1 1
-1 1 1 1
counts=8
--------------------------------
Process exited after 2.836 seconds with return value 0
请按任意键继续. . .
分支限界法
#include <cstring>
#include <iostream>
using namespace std;
int paths = 0;
struct Node {
Node* from;
int value;
Node* plus;
Node* zero;
Node* mins; // short of minus
};
Node root = {NULL, 0, NULL, NULL, NULL, false};
int btb(Node* node, int expected, string path) {
if (node->value == expected) {
paths++;
if (node->from->plus->value == expected) {
node->from->plus = NULL;
}
if (node->from->zero->value == expected) {
node->from->zero = NULL;
}
if (node->from->mins->value == expected) {
node->from->mins = NULL;
}
cout << path << endl;
btb(&root, expected, " r ");
}
else {
if (node->plus != NULL) {
btb(node->plus, expected, path + " 1 ");
}
if (node->zero != NULL) {
btb(node->zero, expected, path + " 0 ");
}
if (node->mins != NULL) {
btb(node->mins, expected, path + "-1 ");
}
}
}
Node* btb_tree(int days, int expected, Node* node) {
if (days <= 0) {
btb(&root, expected, "");
return 0;
}
Node plusNode = {NULL, 0, NULL, NULL, NULL, false};
Node zeroNode = {NULL, 0, NULL, NULL, NULL, false};
Node minsNode = {NULL, 0, NULL, NULL, NULL, false};
node->plus = &plusNode;
node->zero = &zeroNode;
node->mins = &minsNode;
plusNode.value = node->value + 1;
zeroNode.value = node->value + 0;
minsNode.value = node->value - 1;
plusNode.from = node;
zeroNode.from = node;
minsNode.from = node;
btb_tree(days - 1, expected, &plusNode);
btb_tree(days - 1, expected, &zeroNode);
btb_tree(days - 1, expected, &minsNode);
}
int main() {
int days = 0;
int expected = 0;
std::cin >> days >> expected;
btb_tree(days, expected, &root);
std::cout << "counts=" << paths << endl;
}
思路
采用分支限界法首先使用btb_tree()
函数构建解空间树,将解空间树传入btb()
函数,遍历输出符合问题解的分支并删除
测试
输入 “3 1”
3 1
1
0 1
0 0 1
-1 1 1
counts=4
--------------------------------
Process exited after 3.556 seconds with return value 0
请按任意键继续. . .
输入"4 2"
4 2
1 1
1 0 1
1 0 0 1
1 -1 1 1
0 1 1
0 1 0 1
1 0 1 1
0 1 1 1
counts=8
--------------------------------
Process exited after 1.969 seconds with return value 0
请按任意键继续. . .