zoukankan      html  css  js  c++  java
  • 【状压dp】CDOJ1608 暑假集训

    裸的状压的话,很显然……但有一个强大的优化。

    就是在枚举决策的时候,固定第一个空位置。可以证明,这样状态数没有减少,但是降低了很多重复访问。

    因为你在枚举的时候,总是可以划分为包含第一个空位置的3个位置;以及不包含第一个空位置的三个位置。这样固定先枚举前者,避免了重复。

    还有一个优化是,没必要每次判断当前集合是否合法。

    因为被更新到过的才是合法的,只需要一开始置成-1,不合法的状态一定不会被更新到。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,a[23][23][23],f[(1<<21)+10];
    char c;
    int ff;
    inline void R(int &x){
        c=0;ff=1;
        for(;c<'0'||c>'9';c=getchar())if(c=='-')ff=-1;
        for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0');
        x*=ff;
    }
    //inline bool check(int S){
    //	int res=0;
    //	for(int i=0;i<n;++i){
    //		res+=((S>>i)&1);
    //	}
    //	return res%3==0;
    //}
    int cans[23*23*23],o;
    int main(){
    	int x,y,z;
    	R(n);
    	for(int i=1;i<=n*(n-1)*(n-2)/6;++i){
    		R(x); R(y); R(z);
    		R(*(*(*(a+x-1)+y-1)+z-1));
    	}
    	memset(f,-1,sizeof(f));
    	f[0]=0;
    	for(int i=0;i<(1<<n);++i){
    //		if(!check(i)){
    //			continue;
    //		}
    		if(f[i]==-1){
    			continue;
    		}
    		o=0;
    		for(int j=0;j<n;++j){
    			if(!((i>>j)&1)){
    				cans[++o]=j;
    			}
    		}
    		for(int k=2;k<=o-1;++k){
    			for(int l=k+1;l<=o;++l){
    				f[i|(1<<cans[1])|(1<<cans[k])|(1<<cans[l])]=max(f[i|(1<<cans[1])|(1<<cans[k])|(1<<cans[l])],f[i]+*(*(*(a+cans[1])+cans[k])+cans[l]));
    			}
    		}
    	}
    	printf("%d
    ",f[(1<<n)-1]);
    	return 0;
    }
  • 相关阅读:
    oracle启动的三步
    Solaris下vi的简单使用帮助
    Solaris下ftp配置(初稿待补充)
    soap笔记1
    Solaris 10 查看机器的网卡mac地址
    查看表空间名称与对应文件
    [转]Ubuntu10.04的网络配置
    [转]红帽企业版RHEL6使用Fedora13的yum源
    [转]linux忘记密码怎么办法
    [转]个人管理 - IT人士书籍推荐(已读)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6935079.html
Copyright © 2011-2022 走看看