zoukankan      html  css  js  c++  java
  • 题解 CF567F 【Mausoleum】

    从放第一本书开始推,每次放两本相同高度的,设 (f_{i,j}) 为左边放i本书,右边放j本书的方案,放书的时候判断一下是否合法,如果合法,(f_{i,j}) += (f_{i-2,j}) , (f_{i-1,j-1}) , (f_{i,j-2}) ,这个方程应该不难理解**

    至于条件可以用邻接表,注意一下邻接表的数据范围,因为书的位置有200个,正反都存一遍就好了

    符号的正反:注意与 >= 相对的是 <= , 不是 <**

    这是我用了 N(N>20) 次调试换来的······

    得到的结果要除以3,因为当放最后两本书时,(f_{i-2,j} == f_{i-1,j-1} == f_{i,j-2})

    具体见代码:

    #include<bits/stdc++.h>
    using namespace std;
    long long n,f[210][210],tot,k,ans;
    long long head[210],next11[410],ver[410],edge[410];
    //一定开long long,一定开long long,一定开long long
    void add(long long x,long long y,long long z){
        next11[++tot]=head[x],ver[tot]=y,edge[tot]=z,head[x]=tot;
    }//邻接表
    
    bool spfa(long long l,long long r,long long ll,long long rr){
    //寻找出边,l表示放的两本书中左边的那本,r是右边那本,
    //ll表示没有放书的区间的左端点,rr表示右端点,
    //可知 ll~rr 中的书高度都大于将要放的两本书
        for(int i=head[l];i;i=next11[i])
        {
            int y=ver[i],z=edge[i];
            if(y==r){
                if(z==2||z==4) return false;
            }//特判,等于的情况只可能:出边为放的另一本书的位置
            else if(z<=2) {
                if(y<ll||y>rr) return false;
            }
            else if(z>=4) {
                if(y>ll&&y<rr) return false;
            }
            else if(z==3) return false;
        }//寻找与左端点有关的条件
        for(long long i=head[r];i;i=next11[i])
        {
            long long y=ver[i],z=edge[i];
            if(y==l){
                if(z==2||z==4) return false;
            }
            else if(z<=2) {
                if(y<ll||y>rr) return false;
            }
            else if(z>=4) {
                if(y>ll&&y<rr) return false;
            }
            else if(z==3) return false;
        }//同上
        return true;
    }
    
    int main(){
        cin>>n>>k;
        for(int i=1;i<=k;i++)
        {
            long long x,y,z=0;
            string c;
            cin>>x>>c>>y;
            if(c[1]=='=')
            {
                if(c[0]=='<') z=1;
                else z=5;
            }
            else {
                if(c[0]=='=') z=3;
                if(c[0]=='<') z=2;
                if(c[0]=='>') z=4;
            }
            if(x==y)
            {
                if(z==2||z==4)
                {
                    cout<<0;
                    return 0;
                }
                else continue;
            }
            add(x,y,z);
            add(y,x,6-z);//懂我为什么强调了吧
        }
        f[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=2*i;j++)
            {
                if(j>=2&&(k==0||spfa(j-1 , j , j+1 , 2*n-2*i+j)))
                    f[j][2*i-j]+=f[j-2][2*i-j];
                if(j>=1&&2*i-j>=1&&(k==0||spfa( j , 2*n-2*i+j+1 , j+1 , 2*n-2*i+j)))
                     f[j][2*i-j]+=f[j-1][2*i-j-1];
                if(2*i-j>=2&&(k==0||spfa(2*n-2*i+j+1 , 2*n-2*i+j+2 , j+1 , 2*n-2*i+j)))
                    f[j][2*i-j]+=f[j][2*i-j-2];
            }//自行理解,最好画个图
        }
        for(int i=0;i<=2*n;i++) ans+=f[i][2*n-i];//ans累加,
        cout<<ans/3;//重要
        return 0;
    }
    
  • 相关阅读:
    【 星 辰 · 第 二 条 约 定 】
    【 星 辰 · 第 一 条 约 定 】
    【 塔 · 第 三 条 约 定 】
    【 塔 · 第 二 条 约 定 】
    某些奇葩的正则校验
    localstorage本地存储的简单使用
    js基础(3)之闭包。
    js基础(2)filter()筛选过滤
    js基础(1)变量作用域
    scrum过程
  • 原文地址:https://www.cnblogs.com/ajy-shi-cj-zui-cai/p/10386726.html
Copyright © 2011-2022 走看看