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 2:
No 3

深度优先搜索,回溯算法的应用。
跟简单版本的题意差不多,在一堆珠串中找Eva想要的,允许有多的,但不允许有缺的,判断能不能找到一些珠串满足条件,如果有多种组合,优先选择多出最少的
我们把所有的珠子按照长度大小排序,那么先找到的肯定剩下的珠子比较少,这个题主要就是测试点3容易超时,超时的原因也很明显,这一批数据找不出目标珠子。那么在开始深搜之前提前判断一下就可以过,但是为了保证dfs的完整性和体现剪枝的作用,我还是决定只写一个dfs函数。

#include<bits/stdc++.h>
using namespace std;
vector<bool>visited;
int min_ = INT_MAX, lack_ = INT_MAX,flag=0;
void dfs(vector<string>& tmp, unordered_map<char, int>& table, int rest, int cur, int lack){
    if(flag||min_ != INT_MAX) return;//如果搜了一遍还是有缺失的珠子,或者已经搜到了,停止搜索
    if(cur==visited.size()&&lack) flag=true;//搜了一遍还是有缺失的珠子
	if (!lack){//lack表示还缺少的珠子,第一次搜到0的时候剩的珠子也是最少的
		min_ = rest;
		return;
	}
	lack_ = min(lack_, lack);//更新还缺少的珠子
	for (int i = cur; i < tmp.size(); i++)
		if (!visited[i]){
			visited[i] = true;
			unordered_map<char, int>mirror = table;
			int cnt = 0;
			for (int j = 0; j < tmp[i].size(); j++)
				if (mirror[tmp[i][j]]){
					mirror[tmp[i][j]]--;
					cnt++;
				}
			dfs(tmp,mirror, rest + tmp[i].size() - cnt, i+1, lack-cnt);
			visited[i] = false;
		}
}
int main()
{
	string a;
	cin >> a;
	unordered_map<char, int>table;
	for (int i = 0; i < a.size(); i++)
		table[a[i]]++;
	int n;
	cin >> n;
	vector<string>tmp(n);
	visited = vector<bool>(tmp.size());
	for (int i = 0; i < n; i++)
		cin >> tmp[i];
	sort(tmp.begin(), tmp.end(), [](string& a, string& b) {return a.size() < b.size();});
	dfs(tmp, table, 0, 0, a.size());
	if (min_ != INT_MAX)
		cout << "Yes " << min_;
	else
		cout << "No " << lack_;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值