动态规划之建造房屋

夏令营:动态规划特训 - 【课后习题】建造房屋 - 蓝桥云课 (lanqiao.cn)

首先,本题让我们求在i个街道总共建造不超过a个房子的最大方案数。每条街道至少建1个。那我们的dp数组基本可以确定是dp[i][j]这个dp数组的含义是在前i个街道总共建造了j个房子的方案数。

那么我们开始考虑状态转移方程。

本题我们可以这么考虑,我们在第i个街道建房子时,建了k个房子,这k从1开始一直到最大值结束。然后前i-1个街道就总共建了m个房子。那么当我们在第i街道建了k个房子,我们的dp数组dp[i][k+m]就是在前i个街道总共建了k+m个房子,由于我们的dp数组的状态不仅仅包含我们在第i街道建了k个房子这一种情况,因为我们想,要是我们前i-1个街道建造m-1个房子而我们在第i个街道键k+1个房子,我们最后也能达到dp[i][k+m]这个状态。但这不要紧,因为我们仅仅针对我们在第i街道建了k个房子这个情况而言,而另一种情况我们也会枚举到。所以我们就有了我们的状态转移方程dp[i][k+m]=dp[i][k+m]+dp[i-1][m].为什么累加,就是因为我之前讲的不仅仅一种情况到达dp[i][k+m]这个状态。有了方程,我们就要写边界,这里的边界没啥实际意义,只是为了迎合我们的状态转移方程罢了,Arrays.fill(dp[0], 1)。我们首先枚举街道从编号1开始,接着我们枚举第i条街道建造了几个房子,在接着我们枚举前i-1个街道总共建了几个房子,这里要注意了,有个小点很重要,那就是我们要在每个街道至少建一个房子,所以我们的第三层循环要从i-1开始,就是前i-1条街每条建造一个。另外我们无需担心k+m超过我们建造的最大房子上线,因为我们只需要得出第i街道建造a个房子即可。

代码


import java.awt.FontFormatException;
import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.AnnotatedWildcardType;
import java.math.BigInteger;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Spliterator.OfPrimitive;
import java.util.function.IntToDoubleFunction;
import java.util.function.LongBinaryOperator;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.management.relation.InvalidRelationTypeException;
import javax.print.attribute.standard.JobMessageFromOperator;
import javax.print.attribute.standard.JobPriority;
import javax.swing.table.TableModel;
import javax.swing.text.TabSet;
public class Main {
  public static void main(String[] args) throws IOException  {
Scanner sc=new Scanner(System.in);
BufferedReader br1=new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw1=new PrintWriter(System.out);
int a=sc.nextInt();
int b=sc.nextInt();
int c=sc.nextInt();
int[][] dp=new int[300][3000];
int d,e,f;
int g=(int)(1000000007);
Arrays.fill(dp[0], 1);
for(d=1;d<=a;d++) {
	for(e=1;e<=b;e++) {
		for(f=d-1;f<=c;f++) {
		dp[d][e+f]=dp[d][e+f]+dp[d-1][f];
		dp[d][e+f]=dp[d][e+f]%g;
		}
	}
}
System.out.println(dp[a][c]);
	}
	
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值