第一行N,M,K(1 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小,接下来K行,每行两个整数x,y,代表(x,y)处有一个蘑菇。
输出一行,代表所求概率(保留到2位小数)
2 2 1 2 1
0.50
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); int m = sc.nextInt(); int k = sc.nextInt(); int[][] xy = new int[k][2]; for (int i = 0; i < k; i++) { xy[i][0] = sc.nextInt(); xy[i][1] = sc.nextInt(); } System.out.printf("%.2f", solve(n, m, xy)); } } private static double solve(int n, int m, int[][] xy) { double[][] map = new double[n + 1][m + 1]; for (int[] a : xy) { map[a[0]][a[1]] = -1; } map[1][1] = 1; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (map[i][j] != -1) { if (map[i - 1][j] != -1) map[i][j] += j == m ? map[i - 1][j] : map[i - 1][j] / 2; if (map[i][j - 1] != -1) map[i][j] += i == n ? map[i][j - 1] : map[i][j - 1] / 2; } } } return map[n][m]; } }
//动态规划的思想
import java.util.*;
public class Main{
public static double dp(int[][] arr,int n,int m){
double[][] res = new double[n+1][m+1];
res[1][1] = 1.0;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
//如果A不在(1,1)位置,此时他有两个方向可以走(向左或者向右),概率均为0.5
//在最后一列和最后一行的时候他只有一个方向可以走,所以概率为1.0 if(!(i == 1 && j == 1)){
res[i][j] = res[i - 1][j] * (j == m ? 1.0 : 0.5) + res[i][j - 1] * (i == n ? 1.0 : 0.5);
}
//如果arr[i][j]位置是蘑菇,则不可能走到该位置,所以该位置的概率为0.0
if(arr[i][j] == 1){
res[i][j] = 0.0;
}
}
}
return res[n][m];
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int m = sc.nextInt();
int[][] arr = new int[n+1][m+1];
int k = sc.nextInt();
while(k != 0){
int x = sc.nextInt();
int y = sc.nextInt();
arr[x][y] = 1;
k--;
}
double result = dp(arr,n,m);
System.out.printf("%.2f\n",result);
}
}
}
#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> using namespace std; int main() { int N,M,K,x,y; double dp[25][25]; bool has[25][25]; while(cin>>N>>M>>K) { memset(dp,0,sizeof(dp)); memset(has,false,sizeof(has)); for(int i=0;i<K;i++) { cin>>x>>y; has[x][y] = true; } for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) { if(i==1 && j==1) { dp[i][j] = 1; continue; } if(has[i][j]) { dp[i][j] = 0; continue; } if(i==N && j==M) { dp[i][j] = dp[i-1][j] + dp[i][j-1]; continue; } if(i==N) { dp[i][j] = dp[i-1][j]*0.5 + dp[i][j-1]; continue; } if(j==M) { dp[i][j] = dp[i-1][j] + dp[i][j-1]*0.5; continue; } if(i==1) { dp[i][j] = dp[i][j-1]*0.5; continue; } if(j==1) { dp[i][j] = dp[i-1][j]*0.5; continue; } dp[i][j] = dp[i-1][j]*0.5 + dp[i][j-1]*0.5; } printf("%.2f\n", dp[N][M]); } return 0; }
//可行路径/总路径的方法不对,讨论里说道用概率求。 #include<iostream> #include<vector> using namespace std; int main(){ int N, M, K; while(cin>>N>>M>>K){ vector<vector<float>> input(N+1, vector<float>(M+1, 0)); int x, y; for(int i = 0; i < K; ++i){ cin>>x>>y; input[x][y] = -1; //-1表示有蘑菇 } for(int i = 1; i <= N; ++i){ for(int j = 1; j <= M; ++j){ if(i==1 && j == 1) input[1][1] = 1; else if(input[i][j] != -1){ if(i != N && j != M) input[i][j] = input[i-1][j]*0.5 + input[i][j-1]*0.5; if(i == N && j != M) input[i][j] = input[i-1][j]*0.5 + input[i][j-1]; if(i != N && j == M) input[i][j] = input[i-1][j] + input[i][j-1]*0.5; if(i == N && j == M) input[i][j] = input[i-1][j] + input[i][j-1]; } else input[i][j] = 0; } } printf("%.2f\n", input[N][M]); } return 0; }
#include <iostream> #include <cstring> using namespace std; int map[26][26]; double dp[26][26]; int N, M, K; void init() { memset(map, 0, sizeof(map)); for(int i = 0; i <= N; i++) for(int j = 0; j <= M; j++) dp[i][j] = 0; } int judge(int x, int y) { return x <= N && x >= 1 && y <= M && y >= 1; } int main() { while(scanf("%d%d%d", &N, &M, &K) != EOF) { init(); for(int i = 0; i < K; i++) { int x; int y; scanf("%d%d", &x, &y); map[x][y] = 1; } dp[1][1] = 1; for(int i = 1; i <= N; i++) { for(int j = 1; j <= M; j++) { if(map[i][j] == 1) dp[i][j] = 0; if(judge(i + 1, j) && judge(i, j + 1)) { dp[i + 1][j] += dp[i][j] * 0.5; dp[i][j + 1] += dp[i][j] * 0.5; } else if(judge(i + 1, j)) dp[i + 1][j] += dp[i][j]; else if(judge(i, j + 1)) dp[i][j + 1] += dp[i][j]; } } printf("%.2lf\n", dp[N][M]); } return 0; } /* 1 0.5 0.25 0.5 0 0.25 0 0 0.25 1 0.5 0.5 1 */
}
//运行通过 #include<iostream> #include<iomanip> using namespace std; int main() { int row, column, block; while (cin >> row >> column >> block) { if (block == 0) cout << setiosflags(ios::fixed) << setprecision(2) << 1.00 << endl; else{ int * xptr = new int[block]; int * yptr = new int[block]; for (int i = 0; i < block; ++i) cin >> xptr[i] >> yptr[i]; double ** iArray = new double*[row + 1]; for (int i = 0; i <= row; ++i) iArray[i] = new double[column + 1]; for (int i = 0; i <= row; ++i) iArray[i][0] = 0.0; for (int j = 0; j <= column; ++j) iArray[0][j] = 0.0; iArray[1][0] = 2.0; for (int i = 1; i <= row; ++i) for (int j = 1; j <= column; ++j) iArray[i][j] = 1.0; for (int i = 0; i < block; ++i) iArray[xptr[i]][yptr[i]] = 0.0; for (int i = 1; i <= row; ++i) for (int j = 1; j <= column; ++j) if (iArray[i][j] == 0.0) continue; else iArray[i][j] = (i == row ? iArray[i][j - 1] : 0.5*iArray[i][j - 1]) + (j == column ? iArray[i - 1][j] : 0.5*iArray[i - 1][j]); cout << setiosflags(ios::fixed) << setprecision(2) << iArray[row][column] << endl; for (int i = 0; i <= row; ++i) delete[]iArray[i]; delete[]iArray; delete[]xptr; delete[]yptr; } } return 0; }
#include <stdlib.h>#include <stdio.h>#include <math.h>//不能用可走路径数/总路径数进行计算//在下边界时,只能向右走,不能向下走,向右概率为1,右边界同理//而在非边界时,向下和向右的概率分别为0.5//我也是在看了Bestmouse皓的java代码意识到的, thsint main(){int n, m;int cn, cm, k;double **b;int i,j;while(~scanf("%d %d %d", &n, &m, &k)){b=new double*[n]();for(i=0; i<n; i++){b[i]=new double[m]();for(j=0; j<m; j++)b[i][j]=1.0;}for(i=0; i<k; i++){scanf("%d %d", &cn, &cm);b[cn-1][cm-1]=0.0;}for(i=1; i<n; i++){if(b[i][0]==0||b[i-1][0]==0)b[i][0]=0;else if(m>1) b[i][0]=0.5*b[i-1][0];}for(j=1; j<m; j++){if(b[0][j]==0||b[0][j-1]==0)b[0][j]=0;else if(n>1) b[0][j]=0.5*b[0][j-1];}for(i=1; i<n; i++){for(j=1; j<m; j++){if(b[i][j]==0.0) continue;else b[i][j]=(j==m-1?1:0.5)*b[i-1][j]+(i==n-1?1:0.5)*b[i][j-1];}}printf("%0.2f\n", b[n-1][m-1]);for(i=0; i<n; i++){delete [] b[i];}delete [] b;}}
#include <iostream> #include <iomanip> #include <vector> #include <algorithm> using namespace std; //到最后一行,向右走的概率为1。同理在最后一列时候,向下走概率也为1。 //其它的都是用 fn[i][j] = 0.5*fn[i][j-1] + 0.5*fn[i-1][j]; int main() { int n,m,k; while (cin>>n>>m>>k) { vector<vector<int>> mp(n+1, vector<int>(m+1, 0)); vector<vector<float>> fn(n+1, vector<float>(m+1, 0)); for (int i = 0; i < k; i++) { int x,y; cin>>x>>y; mp[x][y] = 1; } fn[1][1] = 1.0; for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ if(i==1 && j==1) continue; if(mp[i][j]==1) fn[i][j] = 0.0; else fn[i][j] = (i==n?1:0.5)*fn[i][j-1] + (j==m?1:0.5)*fn[i-1][j]; } } float ans = fn[n][m]; cout.setf(ios::fixed); cout<<setprecision(2)<<ans<<endl; } return 0; }
#include <iostream> #include <vector> #include <iomanip> using namespace std; int main() { int n, m, k, i, j, x, y; vector<int> a; vector<float> p; vector<vector<int>> b; vector<vector<float>> q; while (cin >> n >> m >> k) { for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { a.push_back(0); p.push_back(0.0); } b.push_back(a); q.push_back(p); a.clear(); p.clear(); } for (i = 0; i < k; i++) { cin >> x >> y; b[x - 1][y - 1] = 1; } //--以上都是准备工作----------------------------------------------------- if (n == 1 || m == 1) { float ans = k == 0 ? 1 : 0; cout << fixed << setprecision(2) << ans << endl; } else { for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { if (i == 0 && j == 0) { q[0][0] = 1.0; } else if (i == 0) { q[i][j] = b[i][j] == 0 ? q[i][j - 1] * 0.5 : 0; } else if (j == 0) { q[i][j] = b[i][j] == 0 ? q[i - 1][j] * 0.5 : 0; } else if (i == n - 1 && j > 0 && j < m - 1) { q[i][j] = b[i][j] == 0 ? q[i][j - 1] * 1 + q[i - 1][j] * 0.5 : 0; } else if (j == m - 1 && i > 0 && i < n - 1) { q[i][j] = b[i][j] == 0 ? q[i][j - 1] * 0.5 + q[i - 1][j] * 1 : 0; } else if (i == n - 1 && j == m - 1) { q[i][j] = b[i][j] == 0 ? q[i][j - 1] * 1 + q[i - 1][j] * 1 : 0; } else { q[i][j] = b[i][j] == 0 ? q[i][j - 1] * 0.5 + q[i - 1][j] * 0.5 : 0; } } } cout << fixed << setprecision(2) << q[i - 1][j - 1] << endl; b.clear(); q.clear(); } } return 0; }
递归一下,就没了。#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
bool maze[23][23];
double p[23][23];
int main(){
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k)){
int x,y;
memset(maze,false,sizeof maze);
for(int i = 0;i<k;i++){
scanf("%d%d",&x,&y);
maze[x][y] = true;
}
memset(p,0,sizeof p);
p[1][1] = 1;
for(int i = 1;i<=n;i++)
for(int j = 1;j<=m;j++){
if( maze[i][j])
continue;
double tmp = ((i == n || j == m ) ? 1 : 0.5 ) * p[i][j];
p[i+1][j] += tmp;
p[i][j+1] += tmp;
}
printf("%.2lf\n",p[n][m]);
}
}
//要使用动态规划,注意每个点的概率来源,第一行的点,如(1,3)的概率来源只有它左边点(1,2)的1/2, //第n行的点如(n,3),概率来源为(n,2)+(n-1,3)*1/2,因为(n,2)只能往右走,概率为1。其他的特征点在程序段中列出 #include <iostream> #include <iomanip> #include<cstring> using namespace std; int has[25][25];//有无蘑菇 double dp[25][25];//能够到达每个格子的概率 int main(){ int n, m, k; while(cin >> n >> m >> k){ int i, j; memset(has, 0, sizeof(has)); memset(dp, 0, sizeof(dp)); int x, y; for(i = 0; i < k; ++i){ cin >> x >> y; has[x][y] = 1; } for(i = 1; i <= n; ++i){ for(j = 1; j <= m; ++j){ if(i == 1 && j == 1) {dp[1][1] = 1; continue;} if(has[i][j]) {dp[i][j] = 0; continue;} if(i == n && j == m) {dp[i][j] = dp[i-1][j] + dp[i][j-1]; continue;} if(i == n) {dp[i][j] = dp[i-1][j]*0.5 + dp[i][j-1]; continue;} if(j == m) {dp[i][j] = dp[i-1][j] + dp[i][j-1]*0.5; continue;} if(i == 1) {dp[i][j] = dp[i][j-1]*0.5; continue;} if(j == 1) {dp[i][j] = dp[i-1][j]*0.5; continue;} dp[i][j] = dp[i][j-1]*0.5 + dp[i-1][j]*0.5; } } cout << fixed << setprecision(2) << dp[n][m] << endl; } return 0; }
//直接用概率进行DP,用路径数是不对的 import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sca = new Scanner(System.in); while(sca.hasNext()){ int n = sca.nextInt(); int m = sca.nextInt(); int k = sca.nextInt(); boolean[][] map = new boolean[n][m]; for(int i = 0; i < k; i++) { int x = sca.nextInt()-1; int y = sca.nextInt()-1; map[x][y] = true; } double[][] cw = new double[n][m]; cw[0][0] = 1; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(map[i][j]) cw[i][j] = 0; else if(i == 0 && j == 0) {} else cw[i][j] = (j-1<0?0:(i+1<n?cw[i][j-1]*0.5:cw[i][j-1]))+(i-1<0?0:(j+1<m?cw[i-1][j]*0.5:cw[i-1][j])); //System.out.print(String.format("%.5f",cw[i][j])+" "); } //System.out.println(); } double res = cw[n-1][m-1]; System.out.println(String.format("%.2f", res)); } } }
#include<stdio.h> #include<algorithm> #include<vector> using namespace std; int main(){ int n, m, k; while(scanf("%d%d%d", &n, &m, &k) != EOF){ vector<vector<int>> table((n+1), vector<int>(m+1)); vector<vector<double>> P((n+1), vector<double>(m+1)); int x, y; for(int i = 0; i < k; i++){ scanf("%d%d", &x, &y); table[x][y] = 1; } P[1][1] = 1.0; //起点概率为1 for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(!(i == 1 && j ==1)){ //跳过起点 P[i][j] = P[i-1][j]*(j == m? 1 : 0.5) + P[i][j-1]*(i == n?1:0.5); //边界的时候,概率为1 if(table[i][j] == 1) P[i][j] = 0; //如果该点有蘑菇,概率置为0 } } } printf("%.2lf\n", P[n][m]); } }思路:注意边界就行