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