zoukankan      html  css  js  c++  java
  • Double Elimination CodeForces

    //f[i,j,f1,f2]
    //f1 和 f2 都是01数
    //1表示剩下的人是喜欢的
    //从j开始,长度为2^i个人,胜者组为f1,败者组为f2
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = ((1<<17)+1000);
    int n,k,fans[maxn];
    int dp[18][maxn][2][2];
    //初始化 
    void init() {
    	for(int i=0; i<18; i++) {
    		for(int j=0; j<maxn; j++) {
    			for(int k=0; k<2; k++) {
    				for(int z=0; z<2; z++) {
    					dp[i][j][k][z]=-1e9;
    				}
    			}
    		}
    	}
    }
    int main() {
    	init();
    	cin>>n>>k;
    	for(int i=0; i<k; i++) {
    		int x;
    		cin>>x;
    		fans[x-1]=1;
    	}
    
    	//枚举i
    	for(int i=1; i<=n; i++) {
    		//枚举人 			区间长度
    		for(int j=0; j<(1<<n); j+=(1<<i)) {
    			//等于1,也就是初始化的时候
    			if(i==1) {
    				//表示状态
    				// 比如说 1 和 2
    				//可以1 胜 2 败
    				//也可以2 胜 1 败
    				for(int x1=0; x1<2; x1++) {
    					for(int y1=0; y1<2; y1++) {
    						//
    						if(x1+y1==fans[j]+fans[j+1]) {
    							//只要有一个是喜欢的,那么就有一场比赛
    							dp[i][j][x1][y1]=((fans[j]+fans[j+1])>0?1:0);
    						}
    					}
    				}
    			} else {
    				//进行状态转移 合并
    				//第一个胜者组状况和败者组状况
    				for(int x1=0; x1<2; x1++) {
    					for(int y1=0; y1<2; y1++) {
    						//第二个胜者组状况和败者组状况
    						for(int x2=0; x2<2; x2++) {
    							for(int y2=0; y2<2; y2++) {
    								//一定是x1和x2比赛
    								//y1和y2比赛
    
    								//x1和x2比赛,要么x1输,要么x2输
    								//y1和y2比赛,要么y1输,要么y2输
    								//然后x1或者x2掉下来,再比赛
    								//那么一个就是八种
    
    								//原来两种的方案
    								int cost=dp[i-1][j][x1][y1]+dp[i-1][j+(1<<(i-1))][x2][y2];
    								//胜者组
    								if(x1||x2)
    									cost++;
    								//败者组
    								if(y1||y2)
    									cost++;
    								//直接暴力枚举这八种转移
    								//
    								dp[i][j][x1][x2]=max(dp[i][j][x1][x2],cost+((x2+y1)>0?1:0));
    								dp[i][j][x1][y1]=max(dp[i][j][x1][y1],cost+((x2+y1)>0?1:0));
    
    								dp[i][j][x1][x2]=max(dp[i][j][x1][x2],cost+((x2+y2)>0?1:0));
    								dp[i][j][x1][y2]=max(dp[i][j][x1][y2],cost+((x2+y2)>0?1:0));
    
    								dp[i][j][x2][x1]=max(dp[i][j][x2][x1],cost+((x1+y2)>0?1:0));
    								dp[i][j][x2][y2]=max(dp[i][j][x2][y2],cost+((x1+y2)>0?1:0));
    
    								dp[i][j][x2][x1]=max(dp[i][j][x2][x1],cost+((x1+y1)>0?1:0));
    								dp[i][j][x2][y1]=max(dp[i][j][x2][y1],cost+((x1+y1)>0?1:0));
    							}
    						}
    					}
    				}
    			}
    
    		}
    	}
    
    	int ans = 0;
    	for(int i=0; i<2; i++) {
    		for(int j=0; j<2; j++) {
    			int cost=dp[n][0][i][j];
    			//再判断决赛,是否多看一场
    			if(i+j>0)
    				cost++;
    			ans=max(ans,cost);
    		}
    	}
    	cout<<ans<<endl;
    }
    
  • 相关阅读:
    C语言运算符优先级和口诀
    跨域问题的解决方案 php
    浅谈跨域攻击及预防
    浅析Websocket--PHP
    linux下的删除目录和文件的方法
    python魔法方法
    双指针
    python常用模块
    python三大器
    对闭包的误区
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12501716.html
Copyright © 2011-2022 走看看