接着上一篇:http://blog.youkuaiyun.com/u014473112/article/details/55099044
讨论第三个问题,如果要划分的数n是很大的数比如10^9见woj Problem 1058 - Exchange,用上一种方法就不行了,明显空间是不够的。那么必须考虑用另一种方法,可以发现,在存储dp[i][j]时,需要借用的前面数组的数只用前k行,也就是说,如果要初始化dp[i][j]的值,如果i>=j,dp[i][j]=dp[i-j][j]+dp[i][j-1],这里需要用到第i行以外的数组,就是第i-j行的,而最极端的情况就是第i-k行的,所以我们可以考虑只保留最多第i-k到第i行的数组。那么只需要一个k行k列的数组就可以了,具体代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include <cstring>
using namespace std;
#define LEN 4
long dp[LEN][LEN];
void mov()
{
for(int i=0;i<LEN-1;i++)
for(int j=0;j<LEN;j++)
{
dp[i][j]=dp[i+1][j];
}
}
void work(int n)
{
memset(dp,0,sizeof(dp));
//初始化dp数组
dp[0][0]=1;
dp[1][0]=0;
dp[2][0]=0;
dp[3][0]=0;
int tmp;
for(int i=0;i<=n;i++)
{
//如果i<4,那么久不需要用LEN了
if(i<4)
tmp=i;
else tmp=LEN-1;
for(int j=1;j<=3;j++)
{
if(j<=i)
dp[tmp][j]=dp[tmp-j][j]+dp[tmp][j-1];
else
dp[tmp][j]=dp[tmp][i];
}
if(i>=3)
mov();//如果i>=3,那么就要循环利用dp数组,需要移动数组
}
cout<<dp[tmp][tmp]<<endl;
}
int main()
{
int n;
cin>>n;
while(n!=0)
{
work(n);
cin>>n;
}
}