输出包括一行四个正整数N(2<=N<=5000)、M(1<=M<=N)、K(1<=K<=5000)、P(1<=P<=N)。
输出一个整数,代表最终走到P的方法数对取模后的值。
5 2 3 3
3
1).2->1,1->2,2->3
2).2->3,3->2,2->3
3).2->3,3->4,4->3
1000 1 1000 1
591137401
注意答案要取模
时间复杂度,空间复杂度。
#include<iostream> #include<vector> using namespace std; int main() { int N, M, K, P; int mod = 1e9 + 7; cin >> N >> M >> K >> P; vector<int> list; list.push_back(0); for (int i = 1; i <= N; i++) list.push_back(i); list.push_back(0); vector<int> last(N + 2, 0); last[M] = 1; vector<int> cur(N + 2, 0); for (int step = 0; step < K; step++) { for (int i = 1; i <= N; i++) { cur[i] = (last[i - 1] + last[i + 1])%mod; } for (int i = 1; i <= N; i++) last[i] = cur[i]; } cout << cur[P] << endl; }
#include <bits/stdc++.h> using namespace std; const int MOD = 1000000007; int main(){ int n,m,k,p; cin>>n>>m>>k>>p; int dp[n+1], a[n+1]; memset(a,0,sizeof(a)); memset(dp,0,sizeof(dp)); a[m] = 1; for(int i=1;i<=k;i++){ for(int j=1;j<=n;j++){ if(j==1) dp[j] = a[j+1]; else if(j==n) dp[j] = a[j-1]; else dp[j] = (a[j-1]+a[j+1])%MOD; } for(int j=0;j<=n;j++) a[j] = dp[j]; } cout<<dp[p]<<endl; return 0; }
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int inf=1000000007; int dp[5010][5010]={0}; int main(){ int N,M,K,P; scanf("%d %d %d %d",&N,&M,&K,&P); for(int i=1;i<=N;++i){ if(abs(i-M)==1){ dp[1][i]=1; } } for(int j=2;j<=K;++j){ for(int i=1;i<=N;++i){ if(i==1) dp[j][i]=dp[j-1][i+1]; else if(i==N) dp[j][i]=dp[j-1][i-1]; else dp[j][i]=(dp[j-1][i-1]+dp[j-1][i+1])%inf; } } printf("%d\n",dp[K][P]); }
#include<iostream> #include<vector> #include<algorithm> using namespace std; int mod = 1e9+7; /* 暴力递归->动态规划->空间压缩 解析:当前处于cur位置,还剩rest步要走;1<=cur<=N 1. cur==1,那么下一步只能往右走,也就是走到2,还剩rest-1步; 2. cur==N,那么下一步只能往左走,也就是走到N-1,还剩rest-1步; 3. cur在中间位置,可以往左(cur-1)或者右走(cur+1),还剩rest-1步, 4.终止条件:rest==0,若定在p处,返回1表示能走到,返回0表示未走到; */ int walk1(int N, int cur, int rest, int P) // N:一共N个位置 // cur:当前所处位置 // rest:还剩多少步 // p:目标地点 { if(rest == 0) return cur==P ? 1: 0; if(cur == 1) return walk1(N, 2, rest-1, P); if(cur == N) return walk1(N, N-1, rest-1, P); return walk1(N, cur-1, rest-1, P) + walk1(N, cur+1, rest-1, P); } int walk2(int N, int cur, int rest, int P) /* 考虑dp分析: 1.确定算法无后效性,也就是当前状态到终止状态,与过去状态到达当前状态无关; 2.对可变参数建立table,记录base case;根据base case计算其他未知格子; 3.返回目标格子记录的值; */ { //1.可变参数为cur,cur的范围在N内,还有参数rest; vector<vector<int>> dp(rest+1,vector<int>(N+1, 0)); //当rest为0,那么直接返回0,1(目标位置P); dp[0][P] = 1; //可以推测walk1,中其他的三个情况下,每一个行(rest),都仅仅依赖于上一行的结果(rest-1),因此有了第一行结果,便可 //求解全部的结果 for(int row=1; row<=rest; ++row)//row表步数rest,col表当前位置cur for(int col=1; col<=N; ++col) { if(col==1) dp[row][col] = dp[row-1][2] %mod; //easy error: set 2 else if(col==N) dp[row][col] = dp[row-1][N-1] %mod; //easy error: set 2N-1 else dp[row][col] = (dp[row-1][col-1] + dp[row-1][col+1])%mod; } return dp[rest][cur]%mod; //返回目标步数为rest,终点为P的结果 } int walk3(int N, int cur, int rest, int P) /* dp:每次递增rest,每个位置记录是否满足要求步数抵达的值; */ { //rest为0的dp状态 vector<int> dp(N+1, 0); dp[P] = 1; for(int i=1; i<=rest; ++i) //一直更新到指定步数 { int leftUp = dp[1]; for(int j=1; j<=N; ++j) { int tmp = dp[j]; if(j==1){ dp[j] = dp[2] % mod; //dp[j+1]恰好是上一行右以为的结果,即rest-1,在2位置。 }else if(j==N){ dp[j] = leftUp % mod; //leftUp恰好是上一行左边的结果,即rest-1,在n-1位置。 }else{ dp[j] = (leftUp+dp[j+1]) % mod; } leftUp=tmp; } } return dp[cur] % mod; //从cur开始走rest步的答案 } int main(){ int N, M, K, P; cin >> N >> M >> K >> P; if(N<2 || K<1 || M>N || M<1|| P>N || P<1) return 0; cout << walk3(N, M, K, P) << endl; return 0; }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().split(" "); int n = Integer.parseInt(params[0]); int s = Integer.parseInt(params[1]); int k = Integer.parseInt(params[2]); int e = Integer.parseInt(params[3]); System.out.println(recurrent(n, s, k, e)); } private static int recurrent(int n, int cur, int rest, int end) { if(rest == 0){ // 没有步数了,如果到达了目的地,就生成了一种走法,否则走法无效 return cur == end? 1: 0; }else if(cur == 1){ // 到达左边界,只能往右走,步数减1 return recurrent(n, cur + 1, rest - 1, end, memory) % 1000000007; }else if(cur == n){ // 到达右边界,只能往左走,步数减1 return recurrent(n, cur - 1, rest - 1, end, memory) % 1000000007; }else{ // 中间位置可以往两边走 return (recurrent(n, cur - 1, rest - 1, end, memory) + recurrent(n, cur + 1, rest - 1, end, memory)) % 1000000007; } } }这种递归的做法逻辑还是很清晰的,可以大体上视为每一步都有两种选择,一共有k步,时间复杂度就是2k指数级别,当k很大时会产生指数爆炸,从而超时。假设递归函数为f,仅传入两个变化的参数cur和rest(n,start和end是固定的,这里省略),假设n=5,start=2,k=4,我们要求的是f(2,,4),就会得到如下图的展开:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().split(" "); int n = Integer.parseInt(params[0]); int s = Integer.parseInt(params[1]); int k = Integer.parseInt(params[2]); int e = Integer.parseInt(params[3]); // 初始状态改为无意义的-1 int[][] memory = new int[k + 1][n + 1]; for(int i = 0; i <= k; i++){ for(int j = 0; j <= n; j++) memory[i][j] = -1; } System.out.println(recurrent(n, s, k, e, memory)); } private static int recurrent(int n, int cur, int rest, int end, int[][] memory) { // 有记忆,直接返回 if(memory[rest][cur] != -1) return memory[rest][cur]; if(rest == 0){ // 没有步数了,如果到达了目的地,就生成了一种走法,否则走法无效 memory[rest][cur] = cur == end? 1: 0; }else if(cur == 1){ // 到达左边界,只能往右走,步数减1 memory[rest][cur] = recurrent(n, cur + 1, rest - 1, end, memory) % 1000000007; }else if(cur == n){ // 到达右边界,只能往左走,步数减1 memory[rest][cur] = recurrent(n, cur - 1, rest - 1, end, memory) % 1000000007; }else{ // 中间位置可以往两边走 memory[rest][cur] = (recurrent(n, cur - 1, rest - 1, end, memory) + recurrent(n, cur + 1, rest - 1, end, memory)) % 1000000007; } return memory[rest][cur]; } }仍然是递归,但由于在递归函数的开头就判断了记忆表中是否有f(cur,rest),所以这棵树被进行了大量的剪枝,其实只是不断在填表而已,表的大小是(k+1)*(n+1),因此时间复杂度为O(k*n),以O(k*n)的空间节省了递归展开的时间。
import scala.io.StdIn object Main { def main(args: Array[String]): Unit = { val in = StdIn val params = in.readLine().split(" ") val n = params(0).toInt val start = params(1).toInt val k = params(2).toInt val end = params(3).toInt val dp = Array.ofDim[Int](k + 1, n + 1) dp(0)(end) = 1 // 剩下0步,到达了end,根据递归函数,直接出来一种方案 // 填表,注意第一列是废的 for(rest <- 1 to k; cur <- 1 to n){ if(cur == 1) dp(rest)(cur) = dp(rest - 1)(cur + 1) % 1000000007 else if(cur == n) dp(rest)(cur) = dp(rest - 1)(cur - 1) % 1000000007 else dp(rest)(cur) = (dp(rest - 1)(cur - 1) + dp(rest - 1)(cur + 1)) % 1000000007 } println(dp(k)(start)) } }
import java.util.*; public class Main { public static int mod = (int)1e9+7; public static void main(String[] args) { Scanner scann = new Scanner(System.in); int N = scann.nextInt(); int M = scann.nextInt(); int K = scann.nextInt(); int P = scann.nextInt(); System.out.println(walk(N, M, K, P)); } public static int walk(int N, int M, int K, int P) { if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { return 0; } int[][] dp = new int[K + 1][N + 1]; dp[0][P] = 1; for (int i = 1; i <= K; i++) { for (int j = 1; j <= N; j++) { if (j == 1) { dp[i][j] = dp[i - 1][2] % mod; } else if (j == N) { dp[i][j] = dp[i - 1][N - 1] % mod; } else { dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod; } } } return dp[K][M] % mod; } }
假设有排成一行的N个位置,记为1~N,开始时机器人在M位置,机器人可以往左或者往右走,如果机器人在1位置,那么下一步机器人只能走到2位置,如果机器人在N位置,那么下一步机器人只能走到N-1位置。规定机器人只能走k步,最终能来到P位置的方法有多少种。由于方案数可能比较大,所以答案需要对10^9^+7取模。
输出包括一行四个正整数N(2<=N<=5000)、M(1<=M<=N)、K(1<=K<=5000)、P(1<=P<=N)。
输出一个整数,代表最终走到P的方法数对10^9^+7取模后的值。
5 2 3 3
3
1).2->1,1->2,2->3 2).2->3,3->2,2->3 3).2->3,3->4,4->3
1000 1 1000 1
591137401
注意答案要取模
// 暴力 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int MOD = 1e9 + 10; int n,m,k,p; int DFS(int u,int resi) { if(resi == 0) return u == p ? 1 : 0; int ans = 0; if(u != n) ans = DFS(u + 1,resi - 1) % MOD; if(u != 1) ans += DFS(u - 1,resi - 1) % MOD; return ans % MOD; } int main(void) { cin >> n >> m >> k >> p; cout << DFS(m,k); return 0; }
// 计划性搜索 // 复杂度O(N*K),总有一刻表里填满数据,之后就全是O(1) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 5010,MOD = 1e9 + 7; int f[N][N]; int n,m,k,p; int DFS(int u,int resi) { if(f[u][resi] != -1) return f[u][resi]; if(resi == 0) { f[u][resi] = (u == p) ? 1 : 0; return f[u][resi]; } int ans = 0; if(u != n) ans = DFS(u + 1,resi - 1) % MOD; if(u != 1) ans += DFS(u - 1,resi - 1) % MOD; f[u][resi] = ans % MOD; return f[u][resi]; } int main(void) { cin >> n >> m >> k >> p; memset(f,-1,sizeof f); cout << DFS(m,k); return 0; }
// DP #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 5010,MOD = 1e9 + 7; int f[N][N]; int n,m,k,p; int main(void) { cin >> n >> m >> k >> p; f[m][0] = 1; // row: n, column: k for(int j = 1; j <= k; j++) for(int i = 1; i <= n; i++) f[i][j] = (f[i + 1][j - 1] % MOD + f[i - 1][j - 1] % MOD) % MOD; cout << f[p][k] << endl; return 0; }
// DP + 状态压缩(滚动数组) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 5010,MOD = 1e9 + 7; int f[N],backup[N]; int n,m,k,p; int main(void) { cin >> n >> m >> k >> p; f[m] = 1; for(int j = 1; j <= k; j++) { memcpy(backup,f,sizeof backup); for(int i = 1; i <= n; i++) f[i] = (backup[i + 1] % MOD + backup[i - 1] % MOD) % MOD; } cout << f[p] << endl; return 0; }
#include <bits/stdc++.h> using namespace std; const int mod = 1e9+7; // 取模数 int main() { int n, m, k, p; cin >> n >> m >> k >> p; // 定义 dp[i][j] 表示在只能走 i 步的情况下,到达位置 j 的方案数 vector<vector<int>> dp(k + 1, vector<int>(n + 1, 0)); // 初始化在只能走 1 步的情况下,到达起点 m 的方案数为 1 for(int i = 1; i <= n; ++i){ if(abs(i - m) == 1){ dp[1][i] = 1; } } for(int i = 2; i <= k; ++i){ // 遍历步数 for(int j = 1; j <= n; ++j){ // 遍历位置 // 在1位置,那么下一步机器人只能走到2位置,即往前一步 j+1,同时消耗步数 i-1 if(j == 1) dp[i][j] = dp[i - 1][j + 1]; // 在N位置,那么下一步机器人只能走到N-1位置,即往回一步 j-1,同时消耗步数 i-1 else if(j == n) dp[i][j] = dp[i - 1][j - 1]; //其他情况,可往左或者往右走,即可 j+1 和 j-1,但是都得消耗步数 i-1,同时要取模 else dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod; } } cout << dp[k][p]; // 返回走 k 步情况下,到达终点 p 的方案数 return 0; }
#include<iostream>
#include<vector>
using namespace std;
int main() {
int N, M, K, P;
int mod=1000000007;
cin>>N>>M>>K>>P;
vector<int> pre(N+2,0);
pre[M]=1;
vector<int> res(N+2,0);
for(int i=0;i<K;++i){
for(int j=1;j<=N;++j){
res[j]=(pre[j-1]+pre[j+1])%mod;
//当前步数的情况=上一步中左边的情况+上一步中右边的情况 }
pre=res;
}
cout<<pre[P];
}
#include <iostream> #include <vector> using namespace std; const static int mod = 1e9 + 7; int process(int N, int P, int cur, int rest, vector<vector<int>>& v){ if(v[cur][rest] != -1) return v[cur][rest]; if(rest == 0){ v[cur][rest]= cur == P ? 1 : 0; return v[cur][rest]; } //res > 0 if(cur == 1){ v[cur][rest] = process(N, P, 2, rest - 1, v) % mod; return v[cur][rest]; } if(cur == N){ v[cur][rest] = process(N, P, N - 1, rest - 1, v) % mod; return v[cur][rest]; } //中间位置 v[cur][rest] = (process(N, P, cur + 1, rest - 1, v) % mod + process(N, P, cur - 1, rest - 1, v) % mod) % mod; return v[cur][rest]; } int MemorySearch(int N, int P, int M, int K){ //N + 1行 K + 1列 vector<vector<int>> v(N + 1, vector<int>(K + 1, -1)); return process(N, P, M, K, v); } int main(void){ int N, M, K, P; cin >> N >> M >> K >> P; cout << MemorySearch(N, P, M, K) << endl; return 0; }
#include <iostream> #include <vector> using namespace std; const static int mod = 1e9 + 7; int dp(int N, int K, int M, int P){ vector<vector<int>> dpArr(N + 1, vector<int>(K + 1)); dpArr[P][0] = 1; for(int j = 1; j <= K; j++){ for(int i = 1; i <= N; i++){ if(i == 1) dpArr[i][j] = dpArr[2][j - 1]; else if(i == N) dpArr[i][j] = dpArr[N - 1][j - 1]; else dpArr[i][j] = (dpArr[i + 1][j - 1] % mod + dpArr[i - 1][j - 1] % mod) % mod; } } return dpArr[M][K]; } int main(void){ int N, M, K, P; cin >> N >> M >> K >> P; cout << dp(N, K, M, P) << endl; return 0; }错误原因主要在于if else是否未写对
#include <iostream> #include <vector> using namespace std; const static int mod = 1e9 + 7; int dpProcess(int N, int K, int M, int P){ vector<vector<int>> v(K + 1, vector<int>(N + 1, 0)); v[0][P] = 1; for(int i = 1; i <= K; i++){ for(int j = 1; j <= N; j++){ if(j == 1){ v[i][j] = v[i - 1][j + 1]; } else if(j == N){ v[i][j] = v[i - 1][j - 1]; } else{ v[i][j] = (v[i - 1][j - 1] % mod + v[i - 1][j + 1] % mod) % mod; } } } return v[K][M]; } int main(void){ int N, M, K, P; cin >> N >> M >> K >> P; cout << dpProcess(N, K, M, P) << endl; return 0; }动态规划一定要注意行为个数比较好些。
#include<iostream> #include<cstring> using namespace std; const int N = 5010, mod = 1e9+7; long long f[N], g[N]; int main(){ int n, m, k, p; cin>>n>>m>>k>>p; f[m] = 1; for(int i = 1;i<=k;i++){ memcpy(g, f, sizeof f); for(int j = 1;j<=n;j++) { //cout<<f[j-1]<<" "<<f[j+1]<<endl; f[j] = (g[j-1] + g[j+1])%mod; } } cout<<f[p]<<endl; return 0; }
#include <iostream> #include <vector> #include <math.h> using namespace std; int main() { int n, m, k, p; int t = (int)(pow(10, 9) + 7); while(cin >> n >> m >> k >> p){ vector<vector<int> > dp(k+1,vector<int>(n+1)); // dp[i][j]走i步到达j位置的方法数 = dp[i-1][j-1] + dp[i-1][j+1] for(int i = 1; i <= k; i++){ for(int j = 1; j<= n; j++){ if(i == abs(m-j)) //步数等于始末间距时为1 小于时为0 dp[i][j] = 1; else if(i > abs(m-j) && j == 1) dp[i][j] = dp[i-1][j+1] % t; else if(i > abs(m-j) && j == n) dp[i][j] = dp[i-1][j-1] % t; else if(i > abs(m-j)) dp[i][j] = (dp[i-1][j-1] + dp[i-1][j+1]) % t; } } cout << dp[k][p] << endl; } return 0; }
import java.util.Scanner; public class Main { public static int mod = (int)1e9 + 7; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int M = sc.nextInt(); int K = sc.nextInt(); int P = sc.nextInt(); int[][] dp = new int[K + 1][N + 1]; dp[0][M] = 1; for (int i = 1; i < dp.length; i++) { for (int j = 1; j < dp[0].length; j++) { if (j - 1 > 0) { dp[i][j] += dp[i - 1][j - 1] % mod; } if (j + 1 <= N) { dp[i][j] += dp[i - 1][j + 1] % mod; } } } System.out.println(dp[K][P] % mod); } }
dp数组在每次相加的时候都需要进行mod运算
const [ N, M, K, P ] = readline().split(' ').map(Number); const mod = 10**9 + 7; function dpCreator(rNum, cNum) { const res = []; for (let i = 0; i < rNum; i++) { const row = []; for (let j = 0; j < cNum; j++) { row.push(0); } res.push(row); } return res; } function main(N, M, K, P) { // 这是做过空间压缩后的dp表 // 在二维状态下是 dp[k][cur],表示从位置 cur 开始走 k 步到达目标位置 P 的走法数。 // k 介于 [0...K],前面添加一个 0 表示不走动时的情况; // cur 介于 [0,1,...,N],前面添加一个 0 是为了统一计算,因为在计算 1 位置时,是不需要考虑往 // 左走动的情况的,但是处理从 2 开始的其他位置时,需要用到它左侧 dp[i - 1][j - 1] 的值, // 所以在 1 位置左侧补充一位。 // 在空间压缩、按行滚动计算后,dp 表就成了一维的 const dp = new Array(N + 1).fill(0); // 先初始化 dp 表第一行,表示 K === 0 时,即一步都不走时,到达目标位置 P 的走法数 // 显然只有当起始位置 M === P 时,才会一步都不用走就到目标位置,其他位置是不可能到达的 // 所以只有 dp[0][P] = 1,其他 dp[0][j] 都是 0,这也就是要在 [1...K] 之前再加一个 0 // 的方便之处 dp[P] = 1; for (let i = 1; i <= K; i++) { // 每当在更新新的一行的 dp[j] 位置的值,pre 变量保存的是上一行 dp[j - 1] 的值 // 在内层循环中,在每次将要更新旧的 dp[j] 之前,先用 tmp 变量保存当前行的旧 dp[j] // 在 dp[j] 更新过程中,使用的 pre 其实还是上一行中的 dp[j - 1],而当本轮 dp[j] // 更新完成后,再把 tmp 中的该行旧 dp[j] 放到 pre 中,这样在接下来 j++ 后,pre 就 // 成了上一行的 dp[j - 1] 了 let pre = dp[0]; for (let j = 1; j <= N; j++) { const tmp = dp[j]; if (j === 1) { // 当处于最左侧的 1 位置时,要走到 P(P > 1) 位置,就只能往右走,也就是到 2 // 从 1 到 2 从走法上来说只有一种,而从位置 2 开始再到位置 P,其走法种数完全 // 取决于 dp[i - 1][2],在空间压缩后,因为对于新滚到的一行是从左往右更新 dp[j] // 当处理 dp[j] 时,dp[j + 1] 还是上一行的值,也就是 dp[i - 1][j + 1],此时 j === 1 // 也就是 dp[i - 1][2] // 在二维 dp 表中,相当于 dp[i][j] = dp[i - 1][j + 1] dp[j] = dp[j + 1]; } else if (j === N) { // 当处于最右侧的 N 位置时,要走到 P(P < N) 位置,就只能往左走,也就是到 N - 1 // 和位置 1 的情况类似,此时,dp[i][N] 也等同于 dp[i - 1][N - 1] // 在二维 dp 表中,相当于 dp[i][j] = dp[i - 1][j - 1] // 这里的 pre 就是前面说的动态不断保存 dp[i - 1][j - 1] 的值,此时就是 dp[i - 1][N - 1] dp[j] = pre; } else { // 对于[2...N - 1]的位置而言,都有往左往右两种选择,所以 dp[i][j] 的值是左右两种走法数目之和 // 并注意,在这里就要对结果进行取模,防止数值巨大 // 在二维 dp 表中,相当于 dp[i][j] = (dp[i - 1][j + 1] + dp[i - 1][j - 1]) % mod dp[j] = (dp[j + 1] + pre) % mod; } pre = tmp; } } // 在二维 dp 中相当于 dp[K][M],表示从位置 M 走 K 步达到目标 P 的走法数 return dp[M]; } console.log(main(N, M, K, P));
n,m,k,p = map(int,input().split()) if n < 2&nbs***bsp;k < 1&nbs***bsp;m < 1&nbs***bsp;m > n&nbs***bsp;p < 1&nbs***bsp;p > n: print(0) dp = [0] * (n+1) dp[p-1] = 1 for i in range(k): leftup = dp[0] for j in range(n): temp = dp[j] if j == 0: dp[j] = dp[j+1]%100000007 elif j == n-1: dp[j] = leftup%100000007 else: dp[j] = (leftup + dp[j+1])%100000007 leftup = temp print(dp[m-1])
#include <bits/stdc++.h> using namespace std; int main(){ int N, M, K, P; cin>>N>>M>>K>>P; vector<int> v(N+2, 0); v[M] = 1; int mod = 1e9 + 7; while(K > 0){ K--; int pre = 0; for(int i=1;i<=N;++i){ int cur = (pre + v[i+1])%mod; pre = v[i]; v[i] = cur; } } cout<<v[P]; return 0; }就是前后补个0,完事儿v[i] = v[i-1] + v[i+1]
#include <iostream> #include <vector> using namespace std; int main(){ int n, m, k, p; cin >> n >> m >> k >> p; vector<int> cur(n+2, 0); vector<int> last(n+2,0); int mod = 1e9 + 7; last[m] = 1; for(int step = 0; step < k; ++step){ for(int i = 1; i <= n; ++i){ cur[i] = (last[i-1] + last[i+1]) % mod; } for(int i = 1; i <= n; ++i) last[i] = cur[i]; } cout << cur[p] << endl; return 0; }
import java.util.*; public class Main { public static final int mod = 1_000_000_007; public static int process(int N, int M, int K, int P) { int[] dp = new int[N + 1]; dp[P] = 1; for (int k = 1; k <= K; k++) { int upLeft = dp[1]; for (int i = 1; i <= N; i++) { int tmp = dp[i]; if (i == 1) dp[i] = dp[i + 1]; else if (i == N) dp[i] = upLeft; else dp[i] = (upLeft + dp[i + 1]) % mod; upLeft = tmp; } } return dp[M]; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); // (2<=N<=5000) int M = sc.nextInt(); int K = sc.nextInt(); // (1<=K<=5000) int P = sc.nextInt(); int res = process(N, M, K, P); System.out.println(res); } }
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner scanner = new Scanner(System.in); while(scanner.hasNext()){ // 位置数n int n = scanner.nextInt(); // 当前位置m int m = scanner.nextInt(); // 只能走k步 int k = scanner.nextInt(); // 终点位置p int p = scanner.nextInt(); System.out.println(getCount(n,m,k,p)); } } public static int getCount(int n, int m, int k, int p){ int mod = 1000000007; int[][] dp = new int[k+1][n+1]; for(int i=1;i<=n;i++){ dp[0][i] = i == p ? 1 : 0 ; } for(int i=1;i<=k;i++){ for(int j=1;j<=n;j++){ if(j == 1){ dp[i][j] = dp[i-1][j+1]; }else if(j == n){ dp[i][j] = dp[i-1][j-1]; }else{ // 注意一定要在此处mod,而不是结尾return才mod dp[i][j] = (dp[i-1][j+1]+dp[i-1][j-1]) % mod; } } } return dp[k][m]; } }
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int M = sc.nextInt(); int K = sc.nextInt(); int P = sc.nextInt(); System.out.println(search(N, M, K, P)); } public static int search(int N, int M, int K, int P){ if(N < 2 || K <1 || M < 1 || M > N || P <1 ||P > N){ return 0; } int[][] dp = new int[K+1][N+1]; dp[0][P] = 1; for(int i = 1; i <= K; i++){ for(int j = 1; j <= N; j++){ if(j==1){ dp[i][j] = dp[i-1][2] % (int)(1e9+7); }else if(j == N){ dp[i][j] = dp[i-1][N-1] % (int)(1e9+7); }else{ dp[i][j] = (dp[i-1][j-1]+dp[i-1][j+1])%(int)(1e9+7); } } } return dp[K][M] % (int)(1e9+7); } }