动态规划

来源:互联网 发布:f1 2015知乎 编辑:程序博客网 时间:2024/06/18 15:31

题目一:

现在有两个好友A和B,住在一片长有蘑菇的由n*m个方格组成的草地,A在(1,1),B在(n,m)。现在A想要拜访B,由于她只想去B的家,
所以每次她只会走(i,j+1)或(i+1,j)这样的路线,在草地上有k个蘑菇种在格子里(多个蘑菇可能在同一方格),
问:A如果每一步随机选择的话(若她在边界上,则只有一种选择),那么她不碰到蘑菇走到B的家的概率是多少?

输入描述:

第一行N,M,K(1 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小,接下来K行,每行两个整数x,y,代表(x,y)处有一个蘑菇。

输出描述:

输出一行,代表所求概率(保留到2位小数)
示例1

输入

2 2 12 1

输出

0.50

----------------------------------------------------------------------------------------------------------------------------------------------------------------

思路

用map[i][j]表示蘑菇的位置,用cw[i][j]用来保存到(i,j)点的概率。因为起点为(0,0),终点在第一象限,所以一开始,走的方向

为两个,向上或者向下。所以(i,j)点的位置概率为它之前的点的概率之和。(i,j)点之前的坐标可以表示为(i-1,j)和(i,j-1)。除此之外,还有一个条件,

就是该点是否在边界上,如果在边界上,根据题意,他只有一种选择,即概率为1,要么不在边界,则概率为0.5。

代码:

import java.util.Scanner;public class CountBroohPath {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while(scanner.hasNext()){int n = scanner.nextInt();int m = scanner.nextInt();int k = scanner.nextInt();boolean[][] map = new boolean[n][m];//题目中描述出发点为(0,0)for(int i=0;i<k;i++){//由于题目中描述数组从1开始,所以在这里减1int x = scanner.nextInt()-1;int y = scanner.nextInt()-1;//map用来保存蘑菇所在的点map[x][y]=true;}double[][] cw = new double[n][m];//cw用来保存(i,j)节点的概率。cw[0][0]=1;for(int i=0;i<n;i++){for(int j=0;j<m;j++){//如果该节点存在蘑菇,则这条路不同,所以赋值0if(map[i][j])cw[i][j]=0;else if (i==0 &&  j==0){}else {//j-1<0表示到底边了,i+1<n表示还没到最右边,i-1<0表示还没到最左边,到边的话概率为1,不到边的话概率为0.5//这里加号分成两部分,一部分是按照下右方向走,一个是按照左上方向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]));}}}double res= cw[n-1][m-1];System.out.println(String.format("%.2f", res));}}}

题目二:

现在有一个城市销售经理,需要从公司出发,去拜访市内的商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他只能在左右中选择一个方向,在上下中选择一个方向,现在问他有多少种方案到达商家地址。

给定一个地图map及它的长宽nm,其中1代表经理位置,2代表商家位置,-1代表不能经过的地区,0代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于10。

测试样例:
[[0,1,0],[2,0,0]],2,3
返回:2
-------------------------------------------------------------------------------------------------------------------------
思路
要求从某点到某点的可供选择的路径数。首先从题意中我们可以知道,从起点开始,只有横竖两个方向。
我们可以用map[x][y]表示从起点到当前点的路径数,那么当前的值可以由上一次两个方向的路径数相加得到。
首先可以知道,如果当前点与前一点处于同一行 或者同一列,很显然那路径数就是1,如果与起点处于不同行列的话,
那么map[x][y]=map[x-xd]+map[x][y-yd]。
代码:
public static int countPath(int[][] map, int n, int m){int x1=0; int y1 =0;int x2 = 0;int y2 = 0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){//找到经理所在位置if(map[i][j] ==1){x1 = i;y1 = j;}//找到客户所在位置else if(map[i][j] ==2){x2 = i;y2 = j;}}}//决定x轴和y轴走的方向,int yd = y1 >y2?-1:1;int xd = x1>x2?-1:1;//初始x的位置为经理的x轴位置,每次走xd,当x不等于x2时,执行循环。因为for循环的执行过程,所以循环结束判断需要给x2+xd。for(int x = x1; x!=x2+xd; x+=xd){for(int y=y1;y!=y2+yd;y+=yd){//如果是沿着直线走,则路线为1if(x==x1||y==y1){map[x][y] = map[x][y] == -1?0:1;System.out.println("map["+x+"]["+y+"]: "+map[x][y]);continue;}//如果没有按直线走。则当前可达时,方案数= 上一个(注意是-)沿着x方向走到当前点的方案数 + 上一点沿着y方向走到当前点的方案数。map[x][y]=map[x][y]==-1?0:map[x-xd][y]+map[x][y-yd];}}return map[x2][y2];}
题目三
C市现在要转移一批罪犯到D市,C市有n名罪犯,按照入狱时间有顺序,另外每个罪犯有一个罪行值,值越大罪越重。现在为了方便管理,市长决定转移入狱时间连续的c名犯人,同时要求转移犯人的罪行值之和不超过t,问有多少种选择的方式? 

输入描述:

第一行数据三个整数:n,t,c(1≤n≤2e5,0≤t≤1e9,1≤c≤n),第二行按入狱时间给出每个犯人的罪行值ai(0≤ai≤1e9)

输出描述:

一行输出答案。
--------------------------------------------------------------------------------------------------------
代码
import java.util.Scanner;public class Main{    public static void main(String[] args){        Scanner in=new Scanner(System.in);        while(in.hasNext()){            int n = in.nextInt();//n个人            int t = in.nextInt();//            int c = in.nextInt();//连续c名            int[] a = new int[n];            for(int i = 0;i<n;i++){                a[i] = in.nextInt();            }            int count = 0;            int tempt = 0;            for(int i = 0;i<c;i++){                tempt += a[i];            }            if(tempt<=t)                count++;           for(int i = c;i<a.length;i++){               tempt = tempt+a[i]-a[i-c];               if(tempt<=t)                count++;           }           System.out.println(count);        }    }} 
原创粉丝点击