首页 > 专题系列 > Java解POJ > POJ 3093 Margaritas on the River Walk [解题报告] Java
2013
11-12

POJ 3093 Margaritas on the River Walk [解题报告] Java

Margaritas on the River Walk

问题描述 :

One of the more popular activities in San Antonio is to enjoy margaritas in the park along the river know as the River Walk. Margaritas may be purchased at many establishments along the River Walk from fancy hotels to Joe’s Taco and Margarita stand. (The problem is not to find out how Joe got a liquor license. That involves Texas politics and thus is much too difficult for an ACM contest problem.) The prices of the margaritas vary depending on the amount and quality of the ingredients and the ambience of the establishment. You have allocated a certain amount of money to sampling different margaritas.

Given the price of a single margarita (including applicable taxes and gratuities) at each of the various establishments and the amount allocated to sampling the margaritas, find out how many different maximal combinations, choosing at most one margarita from each establishment, you can purchase. A valid combination must have a total price no more than the allocated amount and the unused amount (allocated amount – total price) must be less than the price of any establishment that was not selected. (Otherwise you could add that establishment to the combination.)

For example, suppose you have $25 to spend and the prices (whole dollar amounts) are:

Vendor A B C D H J
Price 8 9 8 7 16 5

Then possible combinations (with their prices) are:

ABC(25), ABD(24), ABJ(22), ACD(23), ACJ(21), ADJ( 20), AH(24), BCD(24), BCJ(22), BDJ(21), BH(25), CDJ(20), CH(24), DH(23) and HJ(21).

Thus the total number of combinations is 15.

输入:

The input begins with a line containing an integer value specifying the number of datasets that follow, N (1 ≤ N ≤ 1000). Each dataset starts with a line containing two integer values V and D representing the number of vendors (1 ≤ V ≤ 30) and the dollar amount to spend (1 ≤ D ≤ 1000) respectively. The two values will be separated by one or more spaces. The remainder of each dataset consists of one or more lines, each containing one or more integer values representing the cost of a margarita for each vendor. There will be a total of V cost values specified. The cost of a margarita is always at least one (1). Input values will be chosen so the result will fit in a 32 bit unsigned integer.

输出:

For each problem instance, the output will be a single line containing the dataset number, followed by a single space and then the number of combinations for that problem instance.

样例输入:

2
6 25
8 9 8 7 16 5
30 250
1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30

样例输出:

1 15
2 16509438

温馨提示:

Note: Some solution methods for this problem may be exponential in the number of vendors. For these methods, the time limit may be exceeded on problem instances with a large number of vendors such as the second example below.

解题代码:

//* @author: ccQ.SuperSupper
import java.io.*;
import java.util.*;
public class Main {
	
	static final int N = 30+5;
	static final int M = 1000+10;
	static int n,m;
	static int DP[] = new int[M],value[] = new int[N];
	
	public static void main(String []args) throws Exception{
		
		int t,cs=1,i,j;
		//Scanner cin = new Scanner(new FileInputStream("input.txt"));
		Scanner cin = new Scanner(System.in);
		
		t = cin.nextInt();
		while(t--!=0){
			n = cin.nextInt();
			m = cin.nextInt();
			for(i=0;i< n;++i) {
				value[i] = cin.nextInt();
			}
			Arrays.sort(value,0,n);

			System.out.println(cs+" "+solve());
			cs++;
		}
	}
	public static int solve(){
		int i,j,t,sum=0;
		
		for(t=0;t< n;++t){
			init(t);
			for(i=t+1;i< n;++i){
				for(j=m;j>=value[i];--j){
					DP[j] += DP[j-value[i]];
				}
			}
			for(i=m;i>m-value[t] && i>0;--i)
				sum+=DP[i];
		}
		return sum;
	}
	public static void init(int t){
		int i,j=0;
		for(i=0;i<=m;++i) DP[i] = 0;
		for(i=0;i< t;++i)
			j+=value[i];
		if(j<=m)
			DP[j] = 1;
	}
}

  1. 漂亮。佩服。
    P.S. unsigned 应该去掉。换行符是n 不是/n
    还可以稍微优化一下,
    int main() {
    int m,n,ai,aj,bi,bj,ak,bk;
    while (scanf("%d%d",&m,&n)!=EOF) {
    ai = sqrt(m-1);
    bi = sqrt(n-1);
    aj = (m-ai*ai-1)>>1;
    bj = (n-bi*bi-1)>>1;
    ak = ((ai+1)*(ai+1)-m)>>1;
    bk = ((bi+1)*(bi+1)-n)>>1;
    printf("%dn",abs(ai-bi)+abs(aj-bj)+abs(ak-bk));
    }
    }

  2. A猴子认识的所有猴子和B猴子认识的所有猴子都能认识,这句话用《爱屋及乌》描述比较容易理解……

  3. 第二个方法挺不错。NewHead代表新的头节点,通过递归找到最后一个节点之后,就把这个节点赋给NewHead,然后一直返回返回,中途这个值是没有变化的,一边返回一边把相应的指针方向颠倒,最后结束时返回新的头节点到主函数。