• 洛谷P4907【CYH-01】小奔的国庆练习赛 :$A$换$B$ $problem$(DFS,剪枝)


    洛谷题目传送门

    顺便提一下题意有一个地方不太清楚,就是如果输出No还要输出最少需要添加多少张牌才能满足要求。蒟蒻考完以后发现四个点Too short on line 2。。。

    比较需要技巧的搜索

    既然是同一个花色要连续,那就枚举每一个花色在哪一段区间连续并选中四个区间,累计每个点数的选中次数。

    最后来一个(O(13))( ext{check}),首先每个点数选中次数要不少于已有的个数。接着,只有所有点数的选中次数和已有点数相等时,才能判为'Yes',然后统计某张牌的花色的区间未包含这张牌的总数更新答案。否则判为'No',然后统计每个点数选多了的总数更新答案。

    总复杂度(inom{13}{2}^4* 13=481195728),超过了(10^8),肯定需要剪枝。

    可行性剪枝:每个点数选中次数之和不少于原有牌的总数。

    最优性剪枝:实时统计选多了的总数,在No的状态下,如果超过答案则剪掉;在Yes的状态下,只要不为(0)就剪掉。

    700+ms比标程快多了。可能标程比较良心没加什么剪枝。

    #include<bits/stdc++.h>
    #define R register int
    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(R h,R lef){//lef为n-当前已选中总次数
        if(h==5){
            R now=0;
            for(R i=1;i<=13;++i){
                if(cnt[i]>0)return;//不合法
                now|=cnt[i]<0;
            }
            if(now){ans1=now1;return;}//No状态
            for(R i=1;i<=n;++i)//Yes状态,统计答案
                if((l[a[i]]>b[i]||r[a[i]]<b[i])&&++now==ans)return;
            ans=now;ans1=1;return;//注意ans1=1的剪枝作用
        }
        for(R 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(){
        scanf("%d",&n);
        for(R i=1;i<=n;++i){
            scanf("%d%s",&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
    %d
    ",ans);
        else printf("No
    %d
    ",ans1);
        return 0;
    }
    
  • 相关阅读:
    一个或多个listeners启动失败,更多详细信息查看对应的容器日志文件
    java: Compilation failed: internal java compiler error
    新建IEDA项目,运行跳出页面404
    windows版 nvm 1.1.7 安装(填坑)
    向量法求三角形垂点
    error C4430:missing type specifier 解决错误
    QML 从无到有 3 (自动更新)
    QML 从无到有 2 (移动适配)
    QML 从无到有 (基础)
    c++ builder 2010 错误 F1004 Internal compiler error at 0x9740d99 with base 0x9
  • 原文地址:https://www.cnblogs.com/flashhu/p/9740695.html
Copyright © 2020-2023  润新知