• Gym101466I DP 记忆化搜索


    从前往后扫,对于既可以去A班,又可以去B班的人进行决策。

    状态设计有两种姿势。

    第一种姿势比较暴力&玄学:用dp[x][2][y][2]记录下,A班最后一位同学的id,这位同学有没有id比他更小的朋友。对B班也一样. 数组开不下,所以我们可以使用unordered map,但很不幸,这么做会MLE成智障,我们可以加一个小优化:发现了一个解后,直接结束输出Yes。

    code

    #include <iostream>
    #include <vector>
    #include <unordered_map>
    using namespace std;
    const int N=100000+10;
    int n,k,a[N],s[N];
    bool chk1(int x) {
        vector<int> v;
        while(x) v.push_back(x%10), x/=10;
        for(int i=0;i<v.size();i++) 
            if (v[i] != v[v.size()-1-i])
                return 0;
        return 1;
    }
    bool chk2(int x) {
        while(x) {
            if(x%10!=4&&x%10!=7) return 0;
            x/=10;
        }
        return 1;
    }
    unordered_map<int,int> mp[100000+10][2][2];
    
    int dfs(int x,int y,int cx,int cy,int cur) {
        //printf("%d %d %d %d %d
    ", x,y,cx,cy,cur);
        if (cur == n+1) {
            bool ok=0;
            if (cx == 1 && y == 0) ok=1;
            if (cy == 1 && x == 0) ok=1;
            if (cx == 1 && cy == 1) ok = 1;
            if (ok) {
                printf("Yes
    ");
                exit(0);
            }
            return ok;
        }
        if (mp[x][cx][cy].count(y))
            return mp[x][cx][cy][y];
    
        int ret = 0;
        if (s[cur] & 1) {
            if (x == 0) {
                ret = max(ret, dfs(cur,y,0,cy,cur+1));
            } else {
                if (cur-x<=k)
                    ret = max(ret, dfs(cur,y,1,cy,cur+1));
                else {
                    if (cx == 1)
                        ret = max(ret, dfs(cur,y,0,cy,cur+1));
                }
            }
        }
        if (s[cur] & 2) {
            if (y == 0) {
                ret = max(ret, dfs(x,cur,cx,0,cur+1));
            } else {
                if (cur-y<=k)
                    ret = max(ret, dfs(x,cur,cx,1,cur+1));
                else {
                    if (cy == 1)
                        ret = max(ret, dfs(x,cur,cx,0,cur+1));     
                }
            }
        }
        return mp[x][cx][cy][y] = ret;
    }
    int main() {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            if (chk1(a[i])) s[i]|=1;
            if (chk2(a[i])) s[i]|=2;
            if (s[i]==0) return !printf("No
    ");
        }
        printf("%s
    ", dfs(0,0,0,0,1)?"Yes":"No");
    }
    
    

    但是,我们应该相信珂学的!

    我们不妨这么来设计状态:用dp[now][x][y][cx][cy]表示,now位置之前考虑好了,现在在施展now位置。

    1)x: now与上一个A班孩子的距离

    2)y: now与上一个B班孩子的距离。

    注: 当距离大于20时,是没有区别的,所以把大于20的距离都看成21就好了

    3)cx: 上一个A班的孩子有没有朋友

    4)cy: 上一个B班的孩子有没有朋友。

    #include <iostream>
    #include <vector>
    #include <unordered_map>
    #include <bitset>
    using namespace std;
    const int N=100000+10;
    bitset<N> vis[22][22][3][3],dp[22][22][3][3];
    
    int n,k,a[N],s[N];
    
    bool chk1(int x) {
        vector<int> v;
        while(x) v.push_back(x%10), x/=10;
        for(int i=0;i<v.size();i++) 
            if (v[i] != v[v.size()-1-i])
                return 0;
        return 1;
    }                                                               
                                                                
    bool chk2(int x) {
        while(x) {                                                          
            if(x%10!=4&&x%10!=7) return 0;                      
            x/=10;                                                      
        }
        return 1;
    }
    
    int dfs(int now,int dx,int dy,int cx,int cy) {
        //printf("%d %d %d %d %d
    ",now,dx,dy,cx,cy);
        if (now == n+1) {
            if (cx==0||cy==0) return 0;
            return 1;
        }
        if(vis[dx][dy][cx][cy][now]) {
            return dp[dx][dy][cx][cy][now];
        }
        bool ret = 0; vis[dx][dy][cx][cy][now] = 1;
        if (s[now]&1) {
            if (dx==k+1&&cx==0){}
            else ret|=dfs(now+1,1,min(dy+1,k+1),dx<=k?1:0,cy);
        }
        if (s[now]&2) {
            if (dy==k+1&&cy==0) {}
            else ret|=dfs(now+1,min(dx+1,k+1),1,cx,dy<=k?1:0);
        }
    
    
        return dp[dx][dy][cx][cy][now]=ret;
    }
    
    int main() {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            if (chk1(a[i])) s[i]|=1;
            if (chk2(a[i])) s[i]|=2;
            if (s[i]==0) return !printf("No
    ");
        }
        printf("%s
    ", dfs(1,k+1,k+1,1,1)?"Yes":"No");
    }
    
  • 相关阅读:
    .net开发COM组件之组件签名&注册
    msmq访问格式
    IIS宿主WCF服务*.svc Mime类型映射
    匿名方法的机种书写形式
    GMTUTC YYYY-MM-DDTHH:mm:ss.sssZ、YYYY-MM-DDTHH:mm:ss.sss+8:00意义及与北京时间转换
    允许浏览器下载exe.config文件
    WCF部署失败
    原码、补码、反码
    Java 符号引用 与 直接引用
    计算机理论基础知识
  • 原文地址:https://www.cnblogs.com/RUSH-D-CAT/p/9009517.html
Copyright © 2020-2023  润新知