初识dp(简单背包)JAVA版

HDU 4508 湫湫系列故事——减肥记I

这是道完全背包的裸题。AC代码:

思路如下:这里用的是优化过后的一维数组。a[i]:第 i 件食物的幸福值,b[i]:第 i 件食物的卡路里,dp[i]:在 i 卡路里限制下的最大幸福值。

dp[j]=Math.max(dp[j], dp[j-b[i]]+a[i]),j>b[i].顺序遍历,这里刚好与01背包的优化相反,因为这里每种物品都可以有无数种。

import java.util.Scanner;

public class Main
{
	static Scanner scan=new Scanner(System.in);
	public static void main(String[] args)
	{
		while(scan.hasNext())
		{
			int n=scan.nextInt();
			int a[]=new int[n+1];
			int b[]=new int[n+1];
			
			for(int i=1;i<=n;i++)
			{
				a[i]=scan.nextInt();//幸福值
				b[i]=scan.nextInt();//卡路里
			}
			int m=scan.nextInt();
			long dp[]=new long[m+1];
			for(int i=1;i<=n;i++)//i 代表前 i 种食物
				for(int j=b[i];j<=m;j++)//j 代表第 i 种食物所拥有的卡路里
					dp[j]=Math.max(dp[j],dp[j-b[i]]+a[i]);
			System.out.println(dp[m]);	
		}
	}
}


POJ 1014 Dividing

这题可以套进多重背包,可以算是个多重背包的可行性问题吧,AC代码:

思路如下:当大理石们的价值为奇数时,直接不可能平;当大理石们的价值为偶数时,看看在不切割石头的情况下,能否分出价值为总价值一半的大理石。

a[i]:价值为 i 的大理石的个数,dp[i][j]:前 i 种大理石,放入价值容量为 j 的背包(汗,一不小心写出了背包O__O"…那就背包吧)还剩余多少第 i 种大理石,如果值为-1,则表示不可填满。

import java.util.Scanner;

public class Main
{
	static Scanner scan=new Scanner(System.in);
	public static void main(String[] args)
	{
		int cas=0;
		while(scan.hasNext())
		{
			int a[]=new int[7];
			int sum=0;
			for(int i=1;i<a.length;i++)
			{
				a[i]=scan.nextInt();
				sum+=i*a[i];
			}
			
			if(sum==0)
				break;
			System.out.println("Collection #"+(++cas)+":");
			if((sum&1)==1)
			{
				System.out.println("Can't be divided.");
				System.out.println();
			}	
			else
			{
				int total=sum>>1;
				int dp[][]=new int[7][total+1];
				dp[0][0]=0;
				for(int j=1;j<total+1;j++)
					dp[0][j]=-1;
				for(int i=1;i<=6;i++)
				{
					for(int j=0;j<total+1;j++)
						if(dp[i-1][j]>=0)//如果前i-1种大理石能填满容量为 j 的背包,那么
							dp[i][j]=a[i];//用前 i 种大理石去填容量为 j 的背包,必定最多能剩下a[i]个第 i 种大理石
						else//否则~
							dp[i][j]=-1;//就先赋个-1吧~等后面再说
					for(int j=0;j<=total-i;j++)
						if(dp[i][j]>0)//如果前 i 种大理石填满了容量为 j 的背包,则
							dp[i][j+i]=Math.max(dp[i][j+i], dp[i][j]-1);//用前 i 种大理石填满容量为j+i的背包是可能的
				}
				System.out.println(dp[6][total]!=-1?"Can be divided.":"Can't be divided.");
				System.out.println();
			}	
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值