题目大意:给出一个数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;
}