为学论坛“每日一题”系列---数列操作(我的解法有误)

原题目链接:http://www.51weixue.com/thread-678-1-1.html

题目:

给定一个长度为n的非负整数序列n<=100000,只能进行一种操作:选择一个数(不是最后一个)把ai和a(i+1)同时减少1。 问能否经过有限次这样的操作把这个数列变为全0的数列。

输入:长度为n的数组 每个数是正整数
输出:yes 或 no

原来我的解法是错的。。。2 3 3 2,这个序列是可以消去的。。

我的解法,大概就是类似于分治法的思想,将一个数列拆分一个一个小数列,再分别求解:

1、先从简单的几个测试示例找规律,将问题简单化。

当n = 2时,只有两个元素大小相同时,数列才可以变为全0的数列。

当n = 3时,只有当中间元素的大小等于首尾元素大小之和时,数列才可以变为全为的数列。

当n = 4时,可以将这4个元素拆分为两组,也就变成了两个n = 2的情况。所以,可以根据n = 2。

同理,当n = 5时,可以将这5个元素拆分为一个由3个元素组成的小数列和一个由2个元素组成的小数列,再分别求解。

所以当n > 3时,可以将n为解成多个由2个元素和3个元素组成的小数列,然后分别求解,最后合并结果。

一开始是先想到递归解法的,不过既然知道可以拆成由2个元素或者3个元素小数列,那么就可以直接写出非递归解法。


#include<iostream>
#include<cstdio>

const int N = 100000 ;

bool AllToZero(int *A,int n) ; //递归解法
bool All2Zero(int *A ,int n) ; //非递归解法

int main(void)
{
	int i,n ;
	int A[N] ;

	freopen("in.txt","r",stdin) ;


	while(scanf("%d",&n) != EOF)
	{
		for(i = 0 ; i < n ; ++i)
		{
			scanf("%d",&A[i]) ;
		}
		
		if(true == AllToZero(A,n))
		{
			printf("Yes\n") ;
		}
		else
		{
			printf("No\n") ;
		}
	}

	return 0 ;
}


/*递归版本*/
bool AllToZero(int *A,int n) 
{
	if(n > 1)
	{
		return (A[n-1] == A[n-2] && AllToZero(A,n-2)) || (n-3 >= 0 && A[n-2] == A[n-1] + A[n-3] && AllToZero(A,n-3));
	}
	else if(0 == n)
	{
		return true ;
	}
	return false ;
}


/*非递版本*/
bool All2Zero(int *A,int n)
{
	int i = 0 ;

	while(i < n)
	{
		if(i+1 < n && A[i] == A[i+1])
		{
			i += 2 ;
		}
		else if(i+1 < n && i+2 < n && A[i+1] == A[i] + A[i+2])
		{
			i += 3 ; 
		}
		else //一旦发现不能变成0的小数列,立马返回
		{
			return false ;	
		}
	}
	return true ;
}
 

测试数据:

9
1 2 1 4 5 1 2 3 1
5
2 2 3 2 2
8
1 2 1 4 5 1 1 1
6
1 2 1 4 5 1
9
1 2 1 1 1 1 1 1 1 
2
2 2
3
4 1 6

2 6 4 4
1
4
5
1 1 1 1 1





附上别人的一个更好的思路:

最后一个数只能和倒数第二个数同时消去,倒数第二个和最后一个消去之后,只能和倒数第三个同时消去。
按照这个思路,从最后一个数开始,a[i-1] -= a[i],当i-1!=1且a[i-1] < 0时,无解。最后看a[0]是不是为0,如果为0,则yes,否则为no。










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值