Description
Mr Zhou准备了一块nm的巧克力想分给301的小(da)朋友们,强迫症的他想沿着纹路掰成恰好nm个11的小块。
每次他只能拿起一块巧克力,并沿着纹路掰断,这称为一次操作(比如一块34的,一次操作可以掰成两块32的,也可以是31和33的,还可以掰成14和24的)。
经过精密的计算,他算不出最少要掰几次…于是拜托你来算。
现实是残酷的,掰巧克力的时候很难按纹路完美掰成11的,一番努力之后,Mr Zhou只得到了一堆(k块)不规则形状的巧克力碎片。
更不幸的是,301只有sorahjy一个人在努力学(hua)习(shui),Mr Zhou只好和sorahjy一起分而食之。
经过精密的计算,他们算不出怎么尽量平分这些巧克力…于是又拜托你来算。
尽量平分的定义是使得两个人最后的得到的巧克力,质量差的绝对值最小,当然所有巧克力都要被吃完啦,不能剩。
Input
第一行 n m k(1<=n,m<=1000 1<=k<=20)
第二行 k个正整数,表示巧克力碎块的大小,保证碎块大小之和为n*m
Output
第一行,将nm的巧克力块掰成nm个1*1小块所需的最少次数
第二行,将k块巧克力尽量平分后,两人巧克力大小之差的绝对值
Sample Input 1
2 3 4
1 2 1 2
Sample Output 1
5
0
Sample Input 2
10 1 4
6 2 1 1
Sample Output 2
9
2
题解
dp苦手
简单dp。巧克力每掰一次块数+1,掰成nm块,需nm-1次。动态规划状态转移方程:dp[j]=max(dp[j],dp[j-a[i]]+a[i])(其核心为01背包计算最大值)
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
static int n,m,k,s1,s2;
static int dp[]=new int[1000001];
public static void main(String[] args){
Scanner sc=new Scanner(new BufferedInputStream(System.in));
n=sc.nextInt();
m=sc.nextInt();
k=sc.nextInt();
int a[]=new int[k];
for(int i=0;i<k;i++) a[i]=sc.nextInt();
System.out.println(n*m-1);
for (int i = 0; i < k; i++) {
for(int j=n*m/2;j>=a[i];j--){
dp[j]=Math.max(dp[j],dp[j-a[i]]+a[i]);
}
}
System.out.println(Math.abs(dp[n*m/2]-(n*m-dp[n*m/2])));
}
}