USACO_3_1_Stamps

我们面临的基本问题是“邮资为m时可否用少于等于k张邮票来组成”,这是一个yes or no的特殊化问题,它所对应的一般化问题为“组成邮资为m时至少需要多少张邮票”,如果解决了一般化问题则特殊化问题就容易知道了。(想问题时,如果遇到了一个特殊化问题就同时去想想对应的一般化问题,同样,如果遇到一般化问题也同时想想对应的特殊化问题。)

下面简单对“组成邮资为m时至少需要多少张邮票”这个问题给出动规方程。

用values[]表示每种邮票的面值,用needs[i]表示组成邮资 i 至少需要邮票的张数,则有:

needs[i] = min{needs[ i - values[j] ] + 1}, 其中 1 <= j <= n ,且 i - values[j] > 0。

Code
/**//*
ID: sdjllyh1
PROG: stamps
LANG: JAVA
complete date: 2009/1/17
complexity: O(n * m)
author: LiuYongHui From GuiZhou University Of China
more articles: www.cnblogs.com/sdjls
*/


import java.io.*;
import java.util.*;

public class stamps
{
    
private static int n, k;
    
private static int m;
    
private static int[] values;//每种邮票的面值
    private static char[] needs = new char[2000000];//例needs[14]=6时表示组合出面额14至少需要6张邮票

    
public static void main(String[] args) throws IOException
    
{
        init();
        run();
        output();
        System.exit(
0);
    }


    
private static void run()
    
{
        
//先假设组合出每种面值需要很多张邮票
        Arrays.fill(needs, Character.MAX_VALUE);
        
//设置那些可用面值仅需要一张邮票
        for (int i = 0; i < n; i++)
        
{
            needs[values[i]] 
= 1;
        }

        
//从m=1开始直到找到一个面额需要的张数大于k
        m = 1;
        
while (needs[m] <= k)
        
{
            m
++;
            
for (int i = 0; i < n; i++)
            
{
                
if (values[i] < m)
                
{
                    needs[m] 
= min(needs[m], (char)(1 + needs[m - values[i]]));
                }

            }

        }

    }


    
private static char min(char c1, char c2)
    
{
        
if (c1 < c2)
        
{
            
return c1;
        }

        
else
        
{
            
return c2;
        }

    }


    
private static void init() throws IOException
    
{
        BufferedReader f 
= new BufferedReader(new FileReader("stamps.in"));
        
char[] buff = new char[1000];
        f.read(buff);
        StringTokenizer st 
= new StringTokenizer(String.valueOf(buff));
        k 
= Integer.parseInt(st.nextToken());
        n 
= Integer.parseInt(st.nextToken());
        values 
= new int[n];
        
for (int i = 0; i < n; i++)
        
{
            values[i] 
= Integer.parseInt(st.nextToken());
        }

        f.close();
    }


    
private static void output() throws IOException
    
{
        PrintWriter out 
= new PrintWriter(new BufferedWriter(new FileWriter("stamps.out")));
        out.println(m 
- 1);
        out.close();
    }

}

你可能感兴趣的:(USACO_3_1_Stamps)