思维,DP - CodeForces 1498C - Planar Reflections

其实dp思路并不难,这里仅仅提一句,solve(n, k, dir)中,dp[p][k][dir]的状态更新与n有关,因此后面的样例不能复用前面的样例得到的状态,必须在每组样例前init dp。
另外我的另一份代码T了,不会分析复杂度。而且这个T的代码本机sample还能出结果,AC代码反而T了。(令人费解?)

1. T代码

#include <bits/stdc++.h>
using namespace std;

const int mod = 1e9+7;
int t;
int n, k;
int dp[1000+5][1000+5][2];

int solve(int p, int k, int dir){ 
	// 该粒子下一个经过的为第p个板子, 向dir方向(0左1右), 衰变为 k; (1 <= p <= n)
    if(p == 0 || k <= 1) return 1;
	else if(dp[p][k][dir] != -1) return dp[p][k][dir];
    else{
        int ans = 1;
        if(dir){
            for(int i = p; i <= n; ++i){
                ans += solve(i-1, k-1, !dir);
                ans %= mod;
            }
        }else{
            for(int i = p; i >= 1; --i){
                ans += solve(i+1, k-1, !dir);
                ans %= mod;
            }
        }
        dp[p][k][dir] = ans;
        return ans;
    }
}

void init(int n, int k){
	for(int i = 1; i <= n; ++i)
		for(int j = 2; j <= k; ++j)
			dp[i][j][0] = dp[i][j][1] = -1;
}
int main(){
    cin >> t;
    while(t--){
        cin >> n >> k;
        init(n, k);
        cout << (solve(1, k, 1) + mod) % mod << endl;
    }
    return 0;
}

image-20210412162315114

2. AC代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1000+5;
const int mod = 1e9+7;
int t;
int n, k;
int dp[N][N][2];

int solve(int p, int k, int dir){ 
	// 一个衰变期为k的粒子, 向dir方向, 碰撞第p个平面
    if(k == 1) return 1;
	else if(dp[p][k][dir] != -1) return dp[p][k][dir];
    else{
        int ans = 2;
        if(dir){
            if(p < n)
                ans += solve(p+1, k, dir) - 1; // -1 不重复计算衰变其为k的部分
            ans %= mod;

            if(p > 1)
                ans += solve(p-1, k-1, !dir) - 1; // -1 不重复计算衰变期为k-1的部分
            ans %= mod;
        }else{
            if(p > 1)
                ans += solve(p-1, k, dir) - 1;
            ans %= mod;
            if(p < n)
                ans += solve(p+1, k-1, !dir) - 1;
            ans %= mod;
        }
        dp[p][k][dir] = ans;
        return ans;
    }
}


int main(){
    cin >> t;
    memset(dp, -1, sizeof dp);
    while(t--){
        cin >> n >> k;
        memset(dp, -1, sizeof dp);
        cout << (solve(1, k, 1) + mod) % mod << endl;
    }
    return 0;
}

image-20210412162152244

posted @ 2021-04-12 15:34  popozyl  阅读(74)  评论(0编辑  收藏  举报