lightoj 1193 DP

来源:互联网 发布:c语言strtok返回值 编辑:程序博客网 时间:2024/04/29 21:40

一开始的时候用记忆化搜索,直接MLE了,然后直接换成递推的又特么TLE了,然后想办法优化

首先用  sum[i][j] 表示 sum[i][1] + sum[i][2] + ......+ sum[i][j]

当j 〉K时
dp[i][j] = 1 * dp[i-1][j-1] + 2 * dp[i-1][j-2] + 3 * dp[i-1][j-3] + ......+ K * dp[i-1][j-K]
dp[i][j-1] =                  1 * dp[i-1][j-2] + 2 * dp[i-1][j-3] + ......+ ( K - 1 ) * dp[i-1][j-K] + K * dp[i-1][j-K-1]
上面两个坐差
dp[i][j] = dp[i][j-1] + sum[i-1][j-1] - sum[i-1][j-K-1] - K * dp[i-1][j-K-1]
当j <= K时
dp[i][j] = dp[i][j-1] + sum[i-1][j-1]


AC代码如下:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;#define MOD 100000007long long dp[2][16000];long long N, K, S;long long sum[2][16000];int main(){    long long T, Case = 1;    cin >> T;    while( T-- ){        cin >> N >> K >> S;        memset( dp, 0, sizeof( dp ) );        memset( sum, 0, sizeof( sum ) );        int now = 0;        for( int i = 1; i <= S; i++ ){//注意这里一定要更新到S!!!!!!!!!!!!!!!!因为sum为0到i的和!            dp[now][i] = i <= K ? i : 0;            sum[now][i] = ( sum[now][i-1] + dp[now][i] ) % MOD;        }        now ^= 1;        for( int i = 2; i <= N; i++ ){            for( int j = 1; j <= S; j++ ){                if( j <= K ){                    dp[now][j] = ( dp[now][j-1] + sum[now^1][j-1] ) % MOD;                }else{                    dp[now][j] = ( ( dp[now][j-1] + sum[now^1][j-1] - sum[now^1][j-K-1] - K * dp[now^1][j-K-1] ) % MOD + MOD ) % MOD;                }                sum[now][j] = ( sum[now][j-1] + dp[now][j] ) % MOD ;            }            now ^= 1;        }        cout << "Case " << Case++ << ": ";        cout << dp[now^1][S] << endl;    }    return 0;}


0 0
原创粉丝点击