zoukankan      html  css  js  c++  java
  • 【Luogu】P4363一双木棋(状压爆搜)

      题目链接

      唉,只有AC了这道题才会感叹考场上没有想出解法的我是多么智障。

      我甚至连任何想法都没有。

      天啊我当时到底在想些什么。

      AC这道题我就能进前15了诶。

      我们发现只要确定了轮廓线那么此时的状态就是唯一的。

      那么,用15进制的状态去表示一下此时的轮廓线。详细说来,就是我们有n个数,第i个数表示第i行放了多少棋子,然后我们把这n个数用15进制表示一下(为什么不是m+1进制呢?qwq因为15进制写着方便),就可以爆搜啦

      然后因为开O2的关系,map记忆化一下就可以A啦

      

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<map>
    #define maxs 30000020
    #define maxn 120
    #define mod 15
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    map<long long,long long>s;
    
    long long q[maxn][maxn];
    
    long long f[maxs][2];
    bool vis[maxs];
    long long tot;
    long long End;
    long long n,m;
    long long mul[maxn];
    
    inline void check(long long state){    if(s.count(state)==0)    s[state]=++tot;    }
    
    void output(long long ret){
        for(long long i=1;i<=n;++i){
            printf("%lld ",ret%15);
            ret/=15;
        }
        printf("
    ");
        return;
    }
    
    void dfs(long long state){
        //output(state);
        check(state);
        if(vis[s[state]])    return;
        vis[s[state]]=1;
        long long &beta=f[s[state]][0],&alpha=f[s[state]][1];
        if(state==End)    return;
        beta=0x7fffffff;
        long long ret=state,last=m;
        
        for(long long i=1;i<=n;++i){
            long long now=ret%mod;
            if(now<last){
                long long nxt=state-((state/mul[i-1])%mod)*mul[i-1];
                nxt+=(now+1)*mul[i-1];
                //output(state);
                //output(nxt);
                //printf("%d
    ",now);
                dfs(nxt);
                beta=min(beta,f[s[nxt]][1]);
                alpha=max(alpha,f[s[nxt]][0]+q[i][now+1]);
            }
            last=now;
            ret/=mod;
        }
        //output(state);
        //printf("%lld %lld
    ",alpha,beta);
        //printf("
    ");
        return;
    }
    
    int main(){
        n=read(),m=read();
        mul[0]=1;
        for(long long i=1;i<=n;++i)    mul[i]=mul[i-1]*mod;
        long long ans=0;
        for(long long i=1;i<=n;++i)
            for(long long j=1;j<=m;++j)    q[i][j]=read();
        for(long long i=1;i<=n;++i)
            for(long long j=1;j<=m;++j){
                long long x=read();
                ans-=x;
                q[i][j]+=x;
            }
        for(long long i=1;i<=n;++i)    End=(End*mod)+m;
        dfs(0);
        printf("%lld",f[s[0]][1]+ans);
        return 0;
    }
  • 相关阅读:
    在桌面建立快捷方式 Mr
    在窗口中显示一幅 JPG 图象 Mr
    【转载】COM组件设计与应用(一)——起源及复合文件 Mr
    【转载】COM组件设计与应用(二)——GUID和接口 Mr
    关于在Win7 SP1操作系统下编译的ADO应用程序不能在比Win7 SP1版本低的操作系统上运行,微软给出的解释和解决方案 Mr
    Vue UI图形化项目管理使用
    vue+eldialog提交校验
    获取当前日期前一个月日期与天数数组
    element输入框只能输入数字或小数保留两位小数
    vue+ DatePicker日期的加减
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8776101.html
Copyright © 2011-2022 走看看