PAT 1004. To Buy or Not to Buy - Hard Version (35)

Eva would like to make a string of beads with her favorite colors so she went to a small shop to buy some beads. There were many colorful strings of beads. However the owner of the shop would only sell the strings in whole pieces. Hence in some cases Eva might have to buy several strings to get all the beads she needs. With a hundred strings in the shop, Eva needs your help to tell her whether or not she can get all the beads she needs with the least number of extra beads she has to pay for.

For the sake of simplicity, let’s use the characters in the ranges [0-9], [a-z], and [A-Z] to represent the colors. In sample 1, buying the 2nd and the last two strings is the best way since there are only 3 extra beads. In sample 2, buying all the three strings won’t help since there are three “R” beads missing.

Input Specification:

Each input file contains one test case. Each case first gives in a line the string that Eva wants. Then a positive integer N (<=100) is given in the next line, followed by N lines of strings that belong to the shop. All the strings contain no more than 1000 beads.

Output Specification:

For each test case, print your answer in one line. If the answer is “Yes”, then also output the least number of extra beads Eva has to buy; or if the answer is “No”, then also output the number of beads missing from all the strings. There must be exactly 1 space between the answer and the number.
Sample Input 1:

RYg5
8
gY5Ybf
8R5
12346789
gRg8h
5Y37
pRgYgbR52
8Y
8g

Sample Output 1:

Yes 3

Sample Input 2:

YrRR8RRrY
3
ppRGrrYB225
8ppGrrB25
Zd6KrY

Sample Output 1:

No 3

采用的是暴力的方法进行遍历,由于会超时的问题,所以代码中for循环使用40~130的循环以为字符0的ASCii码为48, ‘z’的ASCii码为122,尽可能减少些时间。还要进行一些必要的剪枝操作:
1. 对于暴力遍历时当出现目的串已得到且额外串extra为0,表示已得到最好解答立即结束遍历。
2. 在进行暴力遍历前,先进行判断看是否商店所有的串中可以满足所要求的串,若不满足直接输出答案,不进行遍历操作。
3. 对于商店中不包含所要求串中字符的字符串(即完全不可能买的串),从遍历中剔除。

#include<iostream>
#include<string>

using namespace std;
const int MAX = 99999999;
//由于珠子名称最大为'z'(122)按ASCII码
int dest_beads[130];
int shops_beads[105][130];
int min_extra_beads = MAX;
int min_missing_beads = MAX;
//剪枝操作3
int useful_shop_string_num = 0;

void cal_beads(string s, int array[]){
  bool useful = false;
  for(int i = 0; i < s.length(); i++){
    array[s[i]]++;
    if(dest_beads[s[i]])
      useful = true;
  }
  if(useful)
    useful_shop_string_num++;
  else{
    for(int i = 0; i < 130; i++){
      array[i] = 0;
    }
  }
}

void copy_array(int A1[], int A2[]){
  for(int i = 40; i < 130; i++){
    A2[i] = A1[i];
  }
}
int buy_N_strings(int cur, int dest_beads[], bool *flag){
  int extra_beads = 0;
  int miss_beads = 0;
  for(int i = 40; i < 130; i++){
    if(shops_beads[cur][i] >= dest_beads[i]){
      extra_beads += (shops_beads[cur][i] - dest_beads[i]);
      dest_beads[i] = 0;
    }else{
      dest_beads[i] -= shops_beads[cur][i];
      miss_beads += dest_beads[i];
    }
  }
  if(miss_beads < min_missing_beads)
    min_missing_beads = miss_beads;
  if(!miss_beads)
    *flag = true;
  return extra_beads;
}
//flag 用于判断是否以满足所要求的字符串,flag = true 表示在之前的遍历中以满足要求。
void solve(int N, int dest_beads[], int cur, int extra_beads, bool flag){
//剪枝操作1
  if(!min_extra_beads)
    return;
  if(flag){
    if(min_extra_beads > extra_beads)
      min_extra_beads = extra_beads;
    return;
  }
  if(cur >= N)
     return;
  int tem_beads[130];
  int extra;
  bool tem_flag = flag;
  copy_array(dest_beads, tem_beads);
  //buy cur string
  extra =  buy_N_strings(cur, tem_beads, &tem_flag);
  solve(N, tem_beads, cur + 1,extra_beads + extra, tem_flag);
  //not buy cur string
  solve(N, dest_beads, cur + 1, extra_beads, flag);
}
int preJudge(){
  int miss_bead = 0;
  for(int  i = 40; i < 130; i++){
    if(dest_beads[i]){
      int shop_count = 0;
      for(int j = 0; j < useful_shop_string_num; j++){
        shop_count += shops_beads[j][i];
      }
      if(shop_count < dest_beads[i]){
        miss_bead += (dest_beads[i] - shop_count);
      }
    }
  }
  return miss_bead;
}
int main(){
  string str;
  int N;
  cin >> str >> N;
  cal_beads(str, dest_beads);
  for(int i = 0; i < N; i++){
    cin >> str;
    cal_beads(str, shops_beads[useful_shop_string_num]);
  }
  //剪枝操作2
  int miss_bead = preJudge();
  if(miss_bead){
    cout << "No " << miss_bead << endl;
    return 0;
  }
  solve(useful_shop_string_num, dest_beads, 0, 0, false);
  if(min_extra_beads != MAX){
    cout << "Yes" << " " << min_extra_beads << endl;
  }else{
    cout << "No " << min_missing_beads << endl;
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值