题目链接:
1004 To Buy or Not to Buy - Hard Version (35分)
思路:
1.DFS复杂度根本不敢写,寻思即使剪枝也不会优化太多,然而这题应该就是争对剪枝算法设计的测试点。。所以实在没办法就来一发DFS也未尝不可QAQ
2.将所有0-9 a-z A-Z
转化为整数,然后存储我们需要的颜色和对应个数,再存储每一个商品的颜色和对应个数,先检测可不可以凑齐颜色,可以的话就开始暴力搜索;
3.暴搜的过程中维护一个变量:当前已经买的多余的个数;同时我们还需要维护购买完成时、多余的颜色个数的最小值;如果前者大于等于后者就直接return
实现剪枝;
代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
int f(char& c){
if(c>='0'&&c<='9') return c-'0';
else if(c>='a'&&c<='z') return c-'a'+10;
else return c-'A'+36;
}
const int tt=62;
const int maxn=105;
int n,cost=1<<30,mp[maxn][tt];
vector<int> cnt(tt);
string s,bd[maxn];
void init_(){
for(char& c:s) cnt[f(c)]++;
for(int i=0;i<n;i++) for(char& c:bd[i]) mp[i][f(c)]++;
}
void test(){
int total=0;
for(int i=0;i<tt;i++){
int ans=0;
for(int j=0;j<n;j++) ans+=mp[j][i];
if(ans<cnt[i]) total+=cnt[i]-ans;
}
if(total){cout<<"No "<<total;exit(0);}
}
void dfs(int id,int rcd){
if(id==n||rcd>=cost) return;
vector<int> temp=cnt;
int ext=0; bool flag=true;
for(int i=0;i<tt;i++){
if(mp[id][i]<cnt[i]) flag=false,cnt[i]-=mp[id][i];
else ext+=mp[id][i]-cnt[i],cnt[i]=0;
}
if(flag) cost=min(cost,rcd+ext),cnt=temp;
else dfs(id+1,rcd+ext);
cnt=temp; dfs(id+1,rcd);
}
int main(){
ios::sync_with_stdio(false); cin.tie(nullptr);
// freopen("Sakura.txt","r",stdin);
cin>>s>>n;
for(int i=0;i<n;i++) cin>>bd[i];
init_(); test(); dfs(0,0);
cout<<"Yes "<<cost;
return 0;
}