http://qingtangpaomian.iteye.com/blog/1635988
INPUT FORMAT:
OUTPUT FORMAT:
package session_3_1_6;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;
public class stamps {
public static void main(String[] args) throws Exception {
// Scanner in = new Scanner(System.in);
// PrintWriter pw = new PrintWriter(System.out);
Scanner in = new Scanner(new BufferedReader(new FileReader(
"stamps.in")));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(
"stamps.out")));
int K = in.nextInt();
int N = in.nextInt();
int[] needs = new int[2000000]; //动态规划用数组 , needs[i]表示产生面值为i的邮资所用的最少的邮票数量。
int[] stamps = new int[N]; //输入提供的各种邮票的面值
Arrays.fill(needs, Integer.MAX_VALUE);
for (int j=0;j<N;j++){
stamps[j] = in.nextInt();
}
int i = 0;
needs[0] = 0;
for (;needs[i]<=K;){
i++;
for (int j=0;j<stamps.length;j++){
if (stamps[j]<=i){
needs[i] = min(needs[i] ,needs[i-stamps[j]]+1); //状态转移方程
}
}
}
pw.println(i-1);
pw.close();
}
public static int min(int a , int b){
return a<b?a:b;
}
}
下面是上面题的升级版
http://sfiction.blog.163.com/blog/static/1994040102012520113738298/
给定一个信封,最多只允许粘贴N张邮票,计算在给定K种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max,使得1-max之间的每一个邮资值都能得到。
例如,N=3,K=2,如果面值分别为1分、4分,则在l分-6分之间的每一个邮资值都能得到(当然还有8分、9分和12分):如果面值分别为1分、3 分,则在1分-7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,7分就是可以得到连续的邮资最大值,所以max=7,面值分别为l分、3 分。
[数据范围]
100%的数据,N + K <= 14
这道题真是混蛋……开始是动态规划没写全WA了两次,修正以后无数2B错误连WA三次,唯一的欣慰就是最优解排在第七。
DFS+DP。DFS枚举所有可能的构造方式,用背包解决0..M的面值用当前邮票凑出的最小代价。
/*
ID: Sfiction
OJ: RQNOJ
PROB: 112
*/
#include <stdio.h>
#define M 500
int a[20],f[M],ans[20];
int N,K,MAX,g=1<<29;
void DFS(int k,int s)
{
int i,j,t[M];
if (k==K)
{
if (s>=MAX)
for (MAX=s,i=1;i<=K;i++) ans[i]=a[i];
return;
}
for (i=0;i<M;i++) t[i]=f[i];
for (i=a[k]+1;i<=s;i++)
{
for (j=0;j<M-i;j++)
if (f[j]+1<f[j+i]) f[j+i]=f[j]+1;
for (j=s;f[j]<=N;j++);
a[k+1]=i;
DFS(k+1,j);
for (j=0;j<M;j++) f[j]=t[j];
}
}
int main()
{
int i;
scanf("%d%d",&N,&K);
a[1]=1;
for (i=1;i<=N;i++) f[i]=i;
for (;i<M;i++) f[i]=g;
DFS(1,N+1);
for (i=1;i<=K;i++) printf("%d ",ans[i]);
printf("\nMAX=%d",MAX-1);
return 0;
}