初涉动态规划(学生感想向)

最开始接触动态规划,是因为在做题的时候,遇到了一道题,刚开始我用递归很快就做出来了,但不管我怎样跑,都会时间超限。题是这样的:

拿金币

资源限制

时间限制:1.0s 内存限制:256.0MB

问题描述

  有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。

输入格式

  第一行输入一个正整数n。
  以下n行描述该方格。金币数保证是不超过1000的正整数。

输出格式

  最多能拿金币数量。

样例输入

3
1 3 3
2 2 2
3 1 2

样例输出

11

数据规模和约定

  n<=1000

         最开始我的代码是这样的:

import java.util.*;
public class Main {
	static int sum=0;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int arr[][]=new int[n][n];
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				arr[i][j]=sc.nextInt();
			}
		}
		jinbi(n,0,0,arr,0);
		System.out.println(sum);
	}
	
	static void  jinbi(int n,int x,int y,int[][] arr,int sumi) {
		
		sumi+=arr[x][y];
		
		if(x<n-1) {
			jinbi(n,x+1,y,arr,sumi);
			}
		if(y<n-1)jinbi(n,x,y+1,arr,sumi);
		
		if(x==n-1&&y==n-1&&sumi>sum) {
			sum=sumi;
				
		}	
	}
}

        我这个代码运用了传统递归二叉树的思想,在运算过程中会出现很多重复运算,运算效率不高,时间序是N^x级别的,故多次不能通过。

        所以我去网络上查了这道题的解法,发现解这道题需要用的动态规划的思想:

动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题最短路径问题和复杂系统可靠性问题等中取得了显著的效果

        

         在这道题中:

                1、子问题为:sum(n-1)=sum(n-2)+(n-1)

                2、状态转移方程为:arr[y][x]=arr[y][x]+Math.max(arr[y-1][x],arr[y][x-1])

        所以我写了如下代码:

import java.util.*;
public class Main {
	
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		
		long [][] arr=new long[n][n];

		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr[0].length;j++) {
				arr[i][j]=sc.nextInt();
				
	}
		}
		System.out.println(najinbi(arr,n));
		
		
		
	}
	static long najinbi(long[][] arr,int n) {
		for(int y=0;y<arr.length;y++) {
			for(int x=0;x<arr[0].length;x++) {
		 if(x>0&&y==0) {
			arr[y][x]=arr[y][x]+arr[y][x-1];
		}else if(x==0&&y>0) {
			arr[y][x]=arr[y][x]+arr[y-1][x];
		}else if(y>0) {arr[y][x]=arr[y][x]+Math.max(arr[y-1][x],arr[y][x-1]);}
		}
		}
		
		return arr[n-1][n-1];
		
	}
	
	

	
}

        但是这个代码还是超时间限了,其实是犯了一个很小的错误,因为我以为题目中的数据会很大,其实数据规模只有0——1000,但是我用了long,这导致内存超限。后来我把long改成了int,这样程序就全部通过了。

import java.util.*;
public class Main {
	
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		
		int  [][] arr=new int[n][n];

		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr[0].length;j++) {
				arr[i][j]=sc.nextInt();
				
	}
		}
		System.out.println(najinbi(arr,n));
		
		
		
	}
	static int  najinbi(int [][] arr,int n) {
		for(int y=0;y<arr.length;y++) {
			for(int x=0;x<arr[0].length;x++) {
		 if(x>0&&y==0) {
			arr[y][x]=arr[y][x]+arr[y][x-1];
		}else if(x==0&&y>0) {
			arr[y][x]=arr[y][x]+arr[y-1][x];
		}else if(y>0) {arr[y][x]=arr[y][x]+Math.max(arr[y-1][x],arr[y][x-1]);}
		}
		}
		
		return arr[n-1][n-1];
		
	}
	
	

	
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值