PKU1010解題

PKU1010
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.
假定你現在在Ruritanian郵政局工作,你的職責是設計他們的郵票軟件,該軟件爲根據消費者的需求及庫存的郵票面額來分配郵票。

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.
對Ruritania郵政局發行的郵票感興趣的人超多,作爲對集郵者的一種服務,RPS要求每一種分配郵票的種類數必須最多。另外,爲了使消費都滿意,RPS還發行一些面額相同的郵票(儘管它們的面值相同,但它們確屬於不同的類別),在任何時候,一次發行的郵票種類數不超過25;

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.
爲了節省資金,RPS儘量會少發行面值相同的郵票(因爲他們想儘可能多的發行郵票)。因此,他們一次最多發行4個面額相同的郵票。

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".
對於每一個客戶,你應該輸出符合客戶需求的最好的組合,郵票種類數最大爲4,如果沒有這種組合存在,打印輸出"none“
最好的組合是這樣定義的,它應具有最大種類數的郵票。如果滿足這個條件,有多種方案,那就選擇郵票數量最少的方案,如果還有多種方案,那就選擇最大面額最高的一種方案,如果還有多種方案,那沒轍了,輸出“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.
這也就是說,你應該把客戶的需求打印出來,郵票種類數以及實際的郵票,如果沒有合適的分配,像第二行輸出的那樣,輸出四個‘-’,如果是個死結的話,那就輸出“tie",像最後一行那樣

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

從上午開始做,弄清了題意,又在網上看了網友的解法,大致清楚瞭解題過程,下午開始編程,在對數據的組合上花費了很多時間,到晚上終於把程序寫完了,提交,AC了,哈哈。

這道題並非是很難的題,如果在第一步就過去的話,後面的便很容易了處理了。難在哪裏呢,難在如何將一堆數進行組合,題目中已經說明了,一次最多隻賣 4張郵票,這什麼意思呢?也就是說只有5種選擇,一種是0張,1張,2張,3張,4張,這樣,我們可以定義一個大小爲4的數組,數組存放郵票的序號,相同的序號代表是同一種郵票,不同的序號代表是不同的郵票,我們可以根據數組的內容來記錄當前郵票的種類數,郵票的張數,還有最大面值值。

而後,再定義一個上限爲25的數組stamps[MAX],來存放郵票的面值,並使用變量stamp_total來記錄輸入的郵票的種類數,這裏要注意了,在將郵票面值插入到stamps末尾時,一定要判斷待插入郵票的面值是否已經在stamps裏存在超過或等於4次,若超過或等於4次,那也就不用插入了。

下面便是關鍵的一步了,我們要找到滿足客戶需求的郵票組合,顯然郵票數組stamps的郵票序號分別是0,1,2,3.。。。我們將從中選取4個序號(序號可相同),如果這4個序號代表的郵票面值和等於客戶需求值,說明這一組郵票爲候選組,對該候選組進行處理即可。

對候選組取其郵票的種類數a1,郵票的張數b1,以及最大面值c1,繼續搜索,尋找下一個候選組,求其郵票的種類數a2,郵票張數b2,最大面值 c2,用題目中給出的條件對a1與a2,b1與b2,c1與c2進行比較,並對候選組進行更新處理。

附上AC後的源代碼:

Source Code
Problem: 1010        User: PJYang
Memory: 692K        Time: 0MS
Language: G++        Result: Accepted

    * Source Code

      #include<iostream>
      using namespace std;

      #define MAX 100
      int stamps[MAX],temp[4],result[4];//stamps數組是輸入的郵票,temp是臨時存儲候選郵票組的序號,result代表是最終選取的候選郵票組
      int request,stamp_total,max_stamps_class,min_stamps,max_stamp_value;//request代表是客戶提供的金額,//stamp_total代表是輸入的郵票總數,max_stamps_class代表是候選郵票的種類數,min_stamps代表是候選郵票的張數, //max_stamp_value代表是最大郵票面值
      bool istie; //是否是死結

    //求候選組的郵票種類數
      int get_total_class()
      {
          int total=0;
          if(temp[3]!=(stamp_total-1))
              total++;
          if(temp[2]<temp[3])
              total++;
          if(temp[1]<temp[2])
              total++;
          if(temp[0]<temp[1])
              total++;

          return total;
      }

      //求候選郵票的張數
      int get_total_stamps()
      {
          int total=0;
          for(int i=0;i<4;i++)
              if(stamps[temp[i]]!=0)
                  total++;
          return total;
      }

      //求候選郵票的最大面值
      int max_value()
      {
          int max=stamps[temp[0]];
          for(int i=1;i<4;i++)
              if(stamps[temp[i]]>max)
                  max=stamps[temp[i]];
          return max;
      }

      //輸入判斷,同種面值的郵票不允許超過4種
      bool lessthan5(int _temp)
      {
          int i,total=0;
          for(i=0;i<stamp_total;i++)
              if(stamps[i]==_temp)
                  total++;
          return total<5;
      }

      //對變量進行初始化
      void init_result()
      {
          for(int i=0;i<4;i++)
          {
              temp[i]=0;
              result[i]=0;
          }

          istie=true;
          max_stamps_class=0;
          min_stamps=5;
          max_stamp_value=0;
      }

      void value_result()
      {
          for(int i=0;i<4;i++)
              result[i]=temp[i];
      }

       //處理過程
      void start_deal()
      {
          int i,j,k,l;
          for(i=0;i<stamp_total;i++)
              for(j=i;j<stamp_total;j++)
                  for(k=j;k<stamp_total;k++)
                      for(l=k;l<stamp_total;l++)
                      {
                          temp[0]=i;
                          temp[1]=j;
                          temp[2]=k;
                          temp[3]=l;
                         
                          if(stamps[i]+stamps[j]+stamps[k]+stamps[l]==request)
                          {
                              int _max_stamps_class=get_total_class();
                              int _min_stamps=get_total_stamps();
                              int _max_value=max_value();

                              if(_max_stamps_class>max_stamps_class)
                              {
                                  istie=false;
                                  max_stamps_class=_max_stamps_class;
                                  min_stamps=_min_stamps;
                                  max_stamp_value=_max_value;
                                  value_result();
                                  continue;
                              }
                              else if(_max_stamps_class==max_stamps_class)
                              {
                                  if(_min_stamps<min_stamps)
                                  {
                                      istie=false;
                                      min_stamps=_min_stamps;
                                      max_stamp_value=_max_value;
                                      value_result();
                                      continue;
                                  }
                                  else if(_min_stamps==min_stamps)
                                  {
                                      if(_max_value>max_stamp_value)
                                      {
                                          istie=false;
                                          value_result();
                                          max_stamp_value=_max_value;
                                          continue;
                                      }
                                      else if(_max_value==max_stamp_value)
                                      {                           
                                          istie=true;
                                      }
                                  }
                              }
                          }
                      }
      }

       //輸出結果
      void print()
      {
          if(max_stamps_class==0)
          {
              cout<<request<<" ---- none"<<endl;
              return;
          }

          cout<<request<<" ("<<max_stamps_class<<"):";

          if(istie)
          {
              cout<<" tie"<<endl;
              return;
          }

          for(int i=0;i<4;i++)
              if(stamps[result[i]]!=0)
                  cout<<" "<<stamps[result[i]];
          cout<<endl;

      }
      int main()
      {
          int stamp_input;
    //輸入郵票
          while(cin>>stamp_input)
          {
              stamps[0]=stamp_input;
              stamp_total=1;

              while(cin>>stamp_input)
              {
                  if(lessthan5(stamp_input))
                  {
                      stamps[stamp_total]=stamp_input;
                      stamp_total++;
                  }

                  if(stamp_input==0) break;
              }
             
        //處理,顯示結果
              while(cin>>request,request)
              {
                  init_result();
                  start_deal();   
                  print();
              }
          }
          return 0;
      }





其實,以上代碼對於匹配郵票對的搜索稍嫌粗糙,寫4個for循環不算什麼,但如果題目要求改變了,莫非你願意去寫20個for循環?我在網上看到一種更好的方法,不過才疏學淺,看了一個下午也沒有看懂,雖然只有短短的幾句話:

int s[6];
void solve(int deep,int n)
{
      if(deep == 5)
      {
        cout<<s[1]<<" "<<s[2]<<" "<<s[3]<<" "<<s[4]<<endl;
        return;
    }
      for(int i = s[deep-1];i <= n; i++)
      {
            s[deep]=i;
            solve(deep+1,n);
      }
}

int main()
{
    int temp;
    while(cin>>temp)
    {
        solve(1,temp);
    }
}

嘻嘻,大家可以試運行下,相信一看結果就明白實現的是什麼功能了,如果將這一段代碼移植到我的程序中,顯然瘦身不少,另外,我的程序是沒有經過優化的,若加以優化,又可以砍掉不少。Oh Yeah! 時間不早了,不寫了,明天開始主攻PKU 1011了。。。

發佈了46 篇原創文章 · 獲贊 79 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章