POJ1010解题报告

STAMPS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 12309 Accepted: 3356

Description

Have you done any Philately lately?

You have been hired by the Ruritanian Postal Service (RPS) to design their new postage software. The software allocates stamps to customers based on customer needs and the denominations that are currently in stock.

Ruritania is filled with people who correspond with stamp collectors. As a service to these people, the RPS asks that all stamp allocations have the maximum number of different types of stamps in it. In fact, the RPS has been known to issue several stamps of the same denomination in order to please customers (these count as different types, even though they are the same denomination). The maximum number of different types of stamps issued at any time is twenty-five.

To save money, the RPS would like to issue as few duplicate stamps as possible (given the constraint that they want to issue as many different types). Further, the RPS won't sell more than four stamps at a time.

Input

The input for your program will be pairs of positive integer sequences, consisting of two lines, alternating until end-of-file. The first sequence are the available values of stamps, while the second sequence is a series of customer requests. For example:

1 2 3 0 ; three different stamp types
7 4 0 ; two customers
1 1 0 ; a new set of stamps (two of the same type)
6 2 3 0 ; three customers

Note: the comments in this example are *not* part of the data file; data files contain only integers.

Output

For each customer, you should print the "best" combination that is exactly equal to the customer's needs, with a maximum of four stamps. If no such combination exists, print "none".
The "best" combination is defined as the maximum number of different stamp types. In case of a tie, the combination with the fewest total stamps is best. If still tied, the set with the highest single-value stamp is best. If there is still a tie, print "tie".

For the sample input file, the output should be:

7 (3): 1 1 2 3
4 (2): 1 3
6 ---- none
2 (2): 1 1
3 (2): tie

That is, you should print the customer request, the number of types sold and the actual stamps. In case of no legal allocation, the line should look like it does in the example, with four hyphens after a space. In the case of a tie, still print the number of types but do not print the allocation (again, as in the example).Don't print extra blank at the end of each line.

Sample Input

1 2 3 0	; three different stamp types
7 4 0		; two customers
1 1 0		; a new set of stamps (two of the same type)
6 2 3 0	; three customers

Sample Output

7 (3): 1 1 2 3 
4 (2): 1 3 
6 ---- none
2 (2): 1 1
3 (2): tie
题意:此题是关于邮票的,可惜我不是集邮爱好者....输入的第一行为邮票的价值value,每一个数值代表一种邮票的价值,直到0结束,邮票的价值可以相同,也可以不同。第二行是用户需要的价值,每个数值代表一个用户的需求,也是到0结束。
按照以下规则为用户选择邮票:
1.选择最多不同种类而又满足用户的邮票
2.如果有两种以上选择满足1,那么在其中选择邮票数目最少的选择。
3.如果有两种以上选择满足2,那么在其中选择最高面额最大的选择。
如果有两种以上选择满足3,那么输出tie;如果没有满足用户需求价值的邮票组合,那么输出none。
 
很明显,如果我们能够列出所有满足用户需求价值的邮票组合,再按照上述的三个条件进行筛选,一定能够最终得出选择的结果。
故,此题为一道典型的搜索题。搜索出所有组合,并进行比较,得出最终结果。
所以我们用record数组记录前一个组合,用current数组记录当前选择,进行比较。
代码如下:
#include<iostream>
#include<algorithm>
#define MAXNUM 100
using namespace std;
int stamp[MAXNUM],record[4],current[4];
int stampnum;
int n; 
int index1=-1,index2=-1,tie=0,found=0;
//最大的值
int maxSingleValue(int a[],int index)
{
    int max=stamp[a[index]];
    int i=0;
    for(i=1;i<=index;i++)
    {
        if(stamp[a[index]]>max)
        {
             max=stamp[a[index]]; 
        }
    } 
    return max;
} 
//邮票的种类
int getType(int a[],int index)
{
     int i,j,tag,num=0;
     for(i=0;i<=index;i++)
     {
          tag=0;
          for(j=0;j<i;j++)
          {
             if(a[j]==a[i])
             {
                 tag=1;
                 break; 
             } 
          }
          if(!tag)
          {
              num++;
          }
     } 
     return num;
} 
void compare()
{
       int j;
       if (index1 ==-1||getType(current,index2) > getType(record,index1)||((getType(current,index2) ==getType(record,index1))&& (index2<index1))||((getType(current,index2) ==getType(record,index1))&&(index1==index2)&&(maxSingleValue(current,index2)>maxSingleValue(record,index1))))
       {
            index1=index2;
            int j=0;
            tie=0;
            for(;j<=index1;j++)
            {
                    record[j]= current[j];
            } 
            return;
        }
        if (getType(current,index2) ==getType(record,index1) && index1==index2&&maxSingleValue(current,index2)==maxSingleValue(record,index1))
        {
            tie = 1;
        }
}
//搜索
void search1(int currentValue,int i)
{
    int k;
    if(currentValue>n)
    {
          return;
    }
    if(currentValue==n)
    {
         //搜索到了某个结果
         found=1;
         int tag=0;
         compare();
    }
    if(index2>=3)
    {
         return; 
    }
    for(k=i;k<=stampnum;k++)
    {
         current[++index2]=k;
         search1(stamp[k]+currentValue,k);
         index2--;
    }
}
    
int main()
{
   int m;
   while(1)
   {
      stampnum=-1;
      //读取邮票 
      if(scanf("%d",&stamp[++stampnum])==EOF)
      {
          break; 
      }
      while(scanf("%d",&n)&&n!=0)
      {
           stamp[++stampnum]=n;
      } 
      while(scanf("%d",&n)&&n!=0)
      {
           //搜索答案 
           tie=0;
           found=0;
           index1=-1;
           index2=-1;
           sort(stamp,stamp+stampnum);
           search1(0,0);
           if(!found)
           {
               printf("%d ---- none\n",n); 
           }
           else if(tie)
           {
               printf("%d (%d): tie\n",n,getType(record,index1)); 
           }
           else 
           {
               printf("%d (%d):",n,getType(record,index1));
               sort(record,record+index1+1);
               for(m=0;m<=index1;m++)
               {
                  printf(" %d",stamp[record[m]]); 
               }
               printf("\n");
           }
      }
   }
   
   system("pause");
   return 0; 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值