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);
    }
    
  • 相关阅读:
    MySQL 配置优化
    django基础之数据库操作
    Python常用内置模块之xml模块
    linux命令总结iostat命令
    springboot接口返回封装与异常控制
    springboot接口访问权限AOP实现
    springboot动态多数据源
    Elasticsearch一些使用笔记(持续更新)
    python语言中的AOP利器:装饰器
    如何使用supervisor管理你的应用
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145649.html
Copyright © 2011-2022 走看看