思维,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;
}
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;
}
---- suffer now and live the rest of your life as a champion ----