最大报销额(一维线性dp)(java)
- 首先要处理这个字符串,用java处理挺麻烦的,尤其是spilt()函数莫名识别不了"."这个字符,幸好后三位是定长的,可以用subString()切割。
- 这个题意描述的也很坑,单项物品不超过600,我以为是单个物品,结果是单类物品。
- 网上答案都是01背包,其实一维的dp就行,f[j]=Math.max(f[j-1], f[x]+can[j]),f[x]是给定值减去第j件物品价值后的最大价值
- 通过这题我也意识到自己造测试案例的重要性,可以反复测试
import java.io.*;
import java.util.Scanner;
public class Main {
static StreamTokenizer s=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static Scanner sc=new Scanner(System.in);
static double can[]=new double[40];
public static void main(String[]args)throws IOException
{
while(sc.hasNext())
{
double f[]=new double[40];
double m=sc.nextDouble();
int n=sc.nextInt();
if(n==0)return;
int idx=0;
for(int i=0;i<n;i++)
{
int n2=sc.nextInt();
boolean flag=false;
double sum=0;
double wa=0,wb=0,wc=0;
for(int j=0;j<n2;j++)
{
String str=sc.next();
String str2[]=str.split(":");
if(!str2[0].equals("A")&&!str2[0].equals("B")&&!str2[0].equals("C"))
{
flag=true;
}
String str3[]=new String[2];
str3[0]=str2[1].substring(0,str2[1].length()-3);
str3[1]=str2[1].substring(str2[1].length()-2,str2[1].length());
if(str2[0].equals("A"))wa+=Integer.parseInt(str3[0])+Integer.parseInt(str3[1])*1.0/100;
else if(str2[0].equals("B"))wb+=Integer.parseInt(str3[0])+Integer.parseInt(str3[1])*1.0/100;
else if(str2[0].equals("C"))wc+=Integer.parseInt(str3[0])+Integer.parseInt(str3[1])*1.0/100;;
if(wa>600||wb>600||wc>600)flag=true;
sum+=Integer.parseInt(str3[0])+Integer.parseInt(str3[1])*1.0/100;
if(sum>1000||Integer.parseInt(str3[0])+Integer.parseInt(str3[1])*1.0/100>600)
{
flag=true;
}
}
if(!flag)
{
can[++idx]=sum;
}
}
for(int j=1;j<=idx;j++)
{
if(can[j]<=m)
{
int x=j;
while(f[--x]+can[j]>m);
f[j]=Math.max(f[j-1], f[x]+can[j]);
}
else {
f[j]=f[j-1];
}
}
System.out.printf("%.2f",f[idx]);
System.out.println();
}
}
public static int nextint()throws IOException
{
s.nextToken();
return (int)s.nval;
}
}