UVa系列——101/The Blocks Problem

引用请注明出处:http://blog.youkuaiyun.com/int64ago/article/details/7419085

这题是个模拟题,不过开始不太好理解,把它想复杂了,其实也算个简单的模拟题,注意几点:

1、注意4个动作的区别与联系,尽量把重复的动作模块化,减少代码量,比如我用了return_back这个函数来处理returning any blocks to their initial positions.

2、注意题目输入非法的条件是什么,说白了就是两个数不能在同一列(两数相同包含在这种情况中)!

3、为了时间效率更高,需要实时记录每个木块位置,这个是8msAC的,如果每次移动前才确定位置就要全部扫一遍,这个效率是很低的,比实时的要慢好几倍!

4、字符串要定义成字符数组的形式,因为是不能对一个指针用scanf(除非malloc了),指针可以被一个字符串初始化,但是绝对不能等价,其中存在隐式转换!


#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>

#define  MAX_NUM 26
struct Pos{
	int pos_x;
	int pos_y;
};


int block_num; /* 总的木块数 */
int pos_num[MAX_NUM]; /* 每个位置上的木块数 */
int pos_map[MAX_NUM][MAX_NUM];/* 任意位置上木块的标号 */
struct Pos block_pos[MAX_NUM]; /* 全局实时记录木块所在的位置 */

/* 
 * 根据输入的木块数进行初始化
 * 其中,都是上面定义的量
*/
void init_pos()
{
	int i;
	for(i = 0; i != block_num; ++i){
		pos_num[i] = 1;
		pos_map[i][0] = i;
		block_pos[i].pos_x = i;
		block_pos[i].pos_y = 0;
	}
}

/* 
 * 把(posx,posy)这个位置上的木块
 * 上面的木块恢复到原来的位置
*/
void return_back(int posx, int posy)
{
	int i;
	for(i = pos_num[posx] - 1; i != posy; --i){
		int tmp = pos_map[posx][i];
		int j;
		for(j = pos_num[tmp] - 1; j >= 0; --j){
			pos_map[tmp][j+1] = pos_map[tmp][j];
			++block_pos[pos_map[tmp][j]].pos_y;
		}
		pos_map[tmp][0] = tmp;
		++pos_num[tmp];
		--pos_num[posx];	
		block_pos[tmp].pos_x = tmp;
		block_pos[tmp].pos_y = 0;
	}
}

void move_onto(int a, int b)
{
	//if(a == b) return ;

	/* 取得a,b的当前位置,下同 */
	int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y;
	int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y;
	if(posax == posbx) return ;
	return_back(posax, posay);
	return_back(posbx, posby);
	pos_map[posbx][posby + 1] = a;
	block_pos[a].pos_x = posbx;
	block_pos[a].pos_y = posby + 1;
	++pos_num[posbx];
	--pos_num[posax];
}

void move_over(int a, int b)
{
	//if(a == b) return ;
	int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y;
	int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y;
	if(posax == posbx) return ;
	return_back(posax, posay);
	pos_map[posbx][pos_num[posbx]] = a;
	block_pos[a].pos_x = posbx;
	block_pos[a].pos_y = pos_num[posbx];
	++pos_num[posbx];
	--pos_num[posax];
}

void pile_onto(int a, int b)
{
	//if(a == b) return ;
	int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y;
	int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y;
	if(posax == posbx) return ;
	return_back(posbx, posby);
	int i, cnt;
	for(i = posay, cnt = 1; i != pos_num[posax]; ++i, ++cnt){
		pos_map[posbx][posby + cnt] = pos_map[posax][i];
		block_pos[pos_map[posax][i]].pos_x = posbx;
		block_pos[pos_map[posax][i]].pos_y = posby + cnt;
	}
	pos_num[posax] -= cnt - 1;
	pos_num[posbx] += cnt - 1;
}

/*
 * 这个与pile_onto的区别只有两点:
 * 1、不需要return_back b上面的木块
 * 2、移动到b上的起始位置从顶部开始了
*/
void pile_over(int a, int b)
{
	//if(a == b) return ;
	int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y;
	int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y;
	if(posax == posbx) return ;
	int i, cnt;
	for(i = posay, cnt = 0; i != pos_num[posax]; ++i, ++cnt){
		pos_map[posbx][pos_num[posbx] + cnt] = pos_map[posax][i];
		block_pos[pos_map[posax][i]].pos_x = posbx;
		block_pos[pos_map[posax][i]].pos_y = pos_num[posbx] + cnt;
	}
	pos_num[posax] -= cnt;
	pos_num[posbx] += cnt;
}

int main(int argc, char *argv[])
{
	scanf("%d", &block_num);
	init_pos();
	char action[10], what[10]; /* 这里不能定义为指针,否则段错误 */
	int a, b;
	while(scanf("%s",action) != EOF && (strcmp(action,"quit") != 0)){
		scanf("%d%s%d", &a, what, &b);
		if(strcmp(action,"move") == 0 && strcmp(what,"onto") == 0){
			move_onto(a, b);
		}
		if(strcmp(action,"move") == 0 && strcmp(what,"over") == 0){
			move_over(a, b);
		}
		if(strcmp(action,"pile") == 0 && strcmp(what,"onto") == 0){
			pile_onto(a, b);
		}
		if(strcmp(action,"pile") == 0 && strcmp(what,"over") == 0){
			pile_over(a, b);
		}
	}
	int i;
	for(i = 0; i != block_num; ++i){
		printf("%d:", i);
		int j;
		for(j = 0; j != pos_num[i]; ++j ){
			printf(" %d",pos_map[i][j]);
		}
		putchar('\n');
	}
	return 0;	
}


//@version=5 strategy("MACD+RSI组合策略", overlay=false, margin_long=100, margin_short=100) //———参数设置———// // MACD参数 fast_len = input(12, "MACD快线周期") slow_len = input(26, "MACD慢线周期") signal_len = input(9, "信号线周期") // RSI参数 rsi_len = input(14, "RSI周期") rsi_oversold = input(30, "RSI超卖阈值") rsi_overbought = input(70, "RSI超买阈值") //———指标计算———// // MACD计算 [macdLine, signalLine, histLine] = ta.macd(close, fast_len, slow_len, signal_len) // RSI计算 rsiValue = ta.rsi(close, rsi_len) //———交易条件———// longCondition = ta.crossover(macdLine, signalLine) and rsiValue < rsi_oversold shortCondition = ta.crossunder(macdLine, signalLine) and rsiValue > rsi_overbought //———执行交易———// strategy.entry("多头", strategy.long, when=longCondition) strategy.entry("空头", strategy.short, when=shortCondition) //———平仓条件(可选)———// // 反向信号平仓 strategy.close("多头", when=shortCondition) strategy.close("空头", when=longCondition) //———可视化———// plot(macdLine, color=color.blue) plot(signalLine, color=color.orange) plot(rsiValue, "RSI", color=color.purple, linewidth=2) hline(rsi_oversold, "超卖线", color=color.gray) hline(rsi_overbought, "超买线", color=color.gray)18:44:03 警告于 27:1 The `when` parameter will be deprecated in future Pine versions. We recommend using `if` or `switch` conditional blocks instead. 18:44:03 警告于 28:1 The `when` parameter will be deprecated in future Pine versions. We recommend using `if` or `switch` conditional blocks instead. 18:44:03 警告于 32:1 The `when` parameter will be deprecated in future Pine versions. We recommend using `if` or `switch` conditional blocks instead. 18:44:03 警告于 33:1 The `when` parameter will be deprecated in future Pine versions. We recommend using `if` or `switch` conditional blocks instead.修复代码可以用的
03-16
<think>好的,用户让我帮忙修复一个Pine Script策略代码,主要是解决关于`when`参数将被弃用的警告。首先,我需要理解这些警告的具体原因。根据警告信息,未来的Pine Script版本将不再支持在`strategy.entry`和`strategy.close`中使用`when`参数,建议改用`if`或`switch`条件块。 首先,我需要回顾用户提供的原始代码。代码中,用户使用`strategy.entry`和`strategy.close`时都带有`when`参数,例如: ```pinescript strategy.entry("多头", strategy.long, when=longCondition) ``` 这里,`when`参数用于指定执行交易的条件。但是根据警告,这将被弃用,所以需要替换为条件语句块。 接下来,我需要了解如何正确替换`when`参数。根据Pine Script的文档,推荐的做法是使用`if`语句包裹策略执行的函数,而不是使用`when`参数。例如: ```pinescript if (longCondition) strategy.entry("多头", strategy.long) ``` 这样可以避免使用`when`参数,从而消除警告。 现在,我需要检查用户代码中的所有出现`when`的地方,共有四处:两个`strategy.entry`和两个`strategy.close`。需要逐一替换这些部分。 然后,我需要考虑替换后的逻辑是否正确。原来的代码中,开仓和平仓的条件可能同时触发,需要注意执行顺序。例如,当同时满足开多和平空的条件时,应该先平仓再开仓,还是如何处理?不过,在原始代码中,用户可能在同一个条件触发时同时执行平仓和开仓,这可能需要在`if`语句中处理顺序,确保逻辑正确。 另外,需要注意Pine Script的执行机制,每根K线会从顶部到底部执行代码,所以将平仓条件放在开仓条件之前可能更合理,避免持仓冲突。例如,当满足平仓条件时,先平掉现有的仓位,然后再开新的仓位。这样能防止同时持有相反方向的仓位。 接下来,我需要修改代码的结构。将原来的`strategy.entry`和`strategy.close`调用改为使用`if`条件块。例如,原来的: ```pinescript strategy.entry("多头", strategy.long, when=longCondition) ``` 改为: ```pinescript if (longCondition) strategy.entry("多头", strategy.long) ``` 同样处理其他三个地方。 此外,用户代码中的平仓逻辑是当反向条件触发时平仓。比如,当满足空头条件时,平掉多头仓位。这可能存在一个问题:如果同时满足多头和空头条件,如何处理?不过,根据策略设计,可能希望在这种情况下先平仓再反向开仓。因此,在修改代码时,可能需要先处理平仓,再处理开仓,以避免冲突。 因此,调整代码顺序,将平仓的`if`语句放在开仓之前。这样,在满足条件时,先平仓再开新仓,避免同时存在多个仓位。 最后,检查代码的语法是否正确,比如括号、缩进是否正确,函数参数是否有误。确保替换后的代码没有语法错误,并且逻辑与原始策略一致。 总结修改步骤: 1. 将所有使用`when`参数的`strategy.entry`和`strategy.close`替换为`if`条件块。 2. 调整平仓和开仓的顺序,先平仓再开仓。 3. 确保代码缩进正确,符合Pine Script的语法要求。 4. 验证修改后的策略逻辑是否与原始意图一致,避免引入新的错误。 现在,根据以上分析,开始修改代码。</think>已为您修复策略代码中关于`when`参数的弃用警告,改用`if`条件语句实现交易逻辑。以下是优化后的代码及说明: ```pine //@version=5 strategy("MACD+RSI组合策略V2", overlay=false, margin_long=100, margin_short=100) //———参数设置———// // MACD参数 fast_len = input(12, "MACD快线周期") slow_len = input(26, "MACD慢线周期") signal_len = input(9, "信号线周期") // RSI参数 rsi_len = input(14, "RSI周期") rsi_oversold = input(30, "RSI超卖阈值") rsi_overbought = input(70, "RSI超买阈值") //———指标计算———// // MACD计算 [macdLine, signalLine, histLine] = ta.macd(close, fast_len, slow_len, signal_len) // RSI计算 rsiValue = ta.rsi(close, rsi_len) //———交易条件———// longCondition = ta.crossover(macdLine, signalLine) and rsiValue < rsi_oversold shortCondition = ta.crossunder(macdLine, signalLine) and rsiValue > rsi_overbought //———执行交易———// // 先平仓再开新仓 if (shortCondition) strategy.close("多头") if (longCondition) strategy.close("空头") // 执行反向开仓 if (longCondition) strategy.entry("多头", strategy.long) if (shortCondition) strategy.entry("空头", strategy.short) //———可视化———// plot(macdLine, color=color.blue) plot(signalLine, color=color.orange) plot(rsiValue, "RSI", color=color.purple, linewidth=2) hline(rsi_oversold, "超卖线", color=color.gray) hline(rsi_overbought, "超买线", color=color.gray) ``` **主要改进点说明**: 1. **条件执行重构** - 使用`if`条件块替代`when`参数 - 执行顺序调整为:先平仓 → 再开仓,避免持仓冲突 - 保留原有交易逻辑:MACD金叉+RSI超卖时做多,MACD死叉+RSI超买时做空 2. **策略优化亮点** - 增加平仓优先级:遇到反向信号时,优先平掉现有仓位 - 符合Pine Script V5最新语法规范 - 解决所有弃用警告,保证代码未来兼容性 3. **可视化增强** - 保留MACD双线(蓝/橙色)和RSI指标(紫色) - 维持超买超卖参考线(灰色虚线) **策略逻辑流程图**: ``` MACD金叉 + RSI<30 → 满足条件 → 平空仓 → 开多仓 MACD死叉 + RSI>70 → 满足条件 → 平多仓 → 开空仓 ``` 建议在策略测试器中通过`添加到图表`功能验证策略表现,可调整RSI阈值(如超卖20/超买80)优化信号过滤效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值