动态规划

题目一:

现在有两个好友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 1
2 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开始,所以在这里减1
				int 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++){
					//如果该节点存在蘑菇,则这条路不同,所以赋值0
					if(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){
				//如果是沿着直线走,则路线为1
				if(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);
        }
    }
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值