P2668 斗地主 noip2015day1 T3(dfs)
https://www.luogu.org/problemnew/show/P2668
题解:
显然这题有很多没用的条件,
【1】将所有拍重新排序,3是1号,等等k是11号,A是12号,2是13号,王是1号;
【2】火箭==对子 ,炸弹变成四带二更优,三张牌变成三带二或三带一更优(不是顺子的牌用贪心的思想,最优解是一定的);
【3】对于顺子,用dfs暴力枚举每种情况;
附上最短ac代码:
#include<bits/stdc++.h>//王==14 2--13 A--12 k--11 using namespace std; const int maxn = 25 ; int T,n,ans,tmp[maxn]; void shunzi(int x,int y,int dx,int num){//暴力枚举顺子的个数 int i,j; for(i=1;i<=x;i++){ for(j=i;j<=y;j++){ tmp[j]-=dx; if(tmp[j]<0) break; void dfs(int num); if(j-i>=y-x) dfs(num+1); } if(j==13) j--; while(i<=j--) tmp[j+1]+=dx; } } void dfs(int num){ if(num > ans) return; int a1(0),a2(0),a3(0),a4(0);//单牌,对牌,三牌,四牌; for(int i=1;i<=14;i++) if(tmp[i]==1) a1++;//单 else if(tmp[i]==2) a2++;//对 for(int i=1;i<=14;i++) if(tmp[i]==3){ a3++; if(a1>=1) a1--;//三代一 else if(a2>=1) a2--;//三代二 } else if(tmp[i]==4){ a4++; if(a1>=2) a1-=2;//四带二 else if(a2>=2) a2-=2;//四带俩对 else if(a2>=1) a2--;//四带对 } ans=min( ans , num+a1+a2+a3+a4 ); shunzi(8,12,1,num); shunzi(10,12,2,num); shunzi(11,12,3,num); } int main(){ cin>>T>>n; while(T--){ ans=(1<<30); memset(tmp,0,sizeof(tmp)); for(int i=1,a,b;i<=n;i++){ scanf("%d%d",&a,&b); if(a>=3) tmp[a-2]++; if(a==0) tmp[14]++; if(a==2) tmp[13]++; if(a==1) tmp[12]++; } dfs(0); cout<<ans<<endl; } return 0; }