洛谷P4907题解
题目传送门
题意:
扑克牌的部分牌被移除,需从剩牌中选 4 个区间,每个区间的牌都是同一花色且点数连续。如果不可选,输出最少需添加几张牌才能满足要求。
思路:
暴力和剪枝。
暴力:按照题意模拟,这样你可以拿到 60 分。
剪枝:
有两种剪枝方法,一种是最优性剪枝,顾名思义,如果当前答案比目前大最优答案大了就剪掉;另一种是可行性剪枝,也就是说当前的不合法了就剪。
#include<bits/stdc++.h>
using namespace std;
const int N = 99;
int a[N],b[N],l[N],r[N],cnt[N],n,now1,ans=N,ans1=N;
char s[N];
void dfs(int h,int lef) { //lef为n-当前已选中总次数if(h==5) {int now=0;for(int i=1; i<=13; ++i) {if(cnt[i]>0) return;//不合法now|=cnt[i]<0;}if(now) {ans1=now1;return;}for(int i=1; i<=n; ++i) if((l[a[i]]>b[i]||r[a[i]]<b[i])&&++now==ans) return;ans=now,ans1=1;return;}for(int i=max(lef-(4-h)*13,0),j,rr; i<=13; ++i) { //枚举区间长度,可行性剪枝if(i==0) {l[h]=r[h]=0;dfs(h+1,lef);continue;}for(rr=i; rr<=13; ++rr) { //右端点for(j=rr-i+1; j<=rr; ++j) now1+=--cnt[j]<0; //动态维护if(now1<ans1) l[h]=(r[h]=rr)-i+1,dfs(h+1,lef-i);//最优性剪枝for(j=rr-i+1; j<=rr; ++j) now1-=++cnt[j]<=0;}}
}
int main() {cin>>n;for(int i=1; i<=n; ++i) {cin>>a[i]>>s;if(s[0]=='A') b[i]=1;else if(s[0]=='1') b[i]=10;else if(s[0]=='J') b[i]=11;else if(s[0]=='Q') b[i]=12;else if(s[0]=='K') b[i]=13;else b[i]=s[0]-'0';++cnt[b[i]];}dfs(1,n);if(ans!=N) printf("Yes\n%d",ans);else printf("No\n%d",ans1);return 0;
}