poj1844 - Sum

133 篇文章 0 订阅

题目大意:给出一个数S,从1到N个数,每个数前面可以是负号或者是正号,这样累加起来,结果

可以等于S,问最小的N是多少。
解题思路:这一题其实和poj1745很相似

拿12举例
12 = -1+2+3+4+5+6-7.

首先进来一个1
那么可以得到1,-1两个值


再来一个2
可以得到
1 + 2 = 3
1 - 2 = -1
-1 + 2 = 1
-1 - 2 = -3
结果有4个值


再来一个3
可以得到
3 + 3 = 6
3 - 3 = 0
-1 + 3 = 2
-1 - 3 = -4
1 + 3 = 4
1 - 3 = -2
-3 + 3 = 0
-3 - 3 = -6
这样有7个值


那么可以发现,每一步都是由上一步的结果而来的,显然可以用动态规划
定义dp[2][200001]代表dp[0][j]和dp[1][j],代表两个相邻的结果,因为每一步的结果只用到上一步的结果,所以只要用2,而j代表结果为j是否成立

#include <iostream>
#include <string.h>
using namespace std;
#define MAXN 200000

int dp[2][MAXN + 1];

int main(){
    int n ,i ,j;
    while(cin>>n){
        memset(dp[1],0,sizeof(dp[1]));	//首先初始第一层结果集
        dp[1][MAXN/2 + 1] = 1;
        dp[1][MAXN/2 - 1] = 1;
        n+=MAXN/2;
        for(i = 2;;i++){	//因为不知道在哪一层,所以来一个死循环
		memset(dp[i&1],0,sizeof(dp[i&1]));	//初始当前结果集
		for(j = 0;j <= MAXN;j++){
                if(dp[(i-1)&1][j]){		//在上一层结果集找
                    if(j + i <= MAXN)   dp[i&1][j + i] = 1;	//在范围内则记录
                    if(j - i >= 0)  dp[i&1][j - i] = 1;
                }
           }
           if(dp[i&1][n]){		//找到n了就退出循环
               cout<<i<<endl;
               break;
           }
        }
    }
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值