zoukankan      html  css  js  c++  java
  • 【BZOJ5248】【九省联考2018】—一双木棋(轮廓线dp)

    传送门

    轮廓线dp入门题

    考虑我们用0/10/1串来表示一个已经选了的点和没选的点之间的轮廓

    如果从左下到右上
    比如向上为0,向右为1,那轮廓线就是一个01串

    我们发现选了一个点实际上只是改变了轮廓方向的顺序

    比如原来是...000111......000111...
    画图发现能填一个点当且仅当轮廓线为0101
    而且填完之后为1010
    可以通过和3进行位运算来判断

    这样就可以妙妙的维护了

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=12;
    int a[N][N],b[N][N];
    int n,m;
    const int inf=1e9;
    int f[1<<21];
    int dfs(int sta,int who){
    	if(f[sta]<=inf)return f[sta];
    	int res=who?-inf:inf;
    	int x=n+1,y=1;
    	for(int i=1;i<=n+m-1;i++){
    		if((sta>>(i-1))&1)x--;else y++;
    		if(((sta>>(i-1))&3)!=1)continue;
    		int nxt=sta^(3<<(i-1));
    		if(who){
    			res=max(res,dfs(nxt,who^1)+a[x][y]);
    		}
    		else res=min(res,dfs(nxt,who^1)-b[x][y]);
    	}
    	return f[sta]=res;
    }
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			a[i][j]=read();
    		}
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			b[i][j]=read();
    		}
    	}
    	memset(f,127,sizeof(f));
    	f[((1<<n)-1)<<m]=0;
    	cout<<dfs((1<<n)-1,1);
    }
    
  • 相关阅读:
    论程序员的自我修养
    设计模式之:行为型设计模式(11种)
    设计模式之:结构型设计模式(7种)
    @import "../style/lines.scss" 导致background: url()路径无效问题
    node express 设置重定向
    png8和png24的区别
    vue scss 使用 及 踩坑
    js 防抖 节流
    js 次方 开方 对数
    css 修改placeholder样式
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145649.html
Copyright © 2011-2022 走看看