zoukankan      html  css  js  c++  java
  • 【BZOJ1306】match循环赛

    预先警告:我的做法代码量比较大

    看完题目后看到数据n<=8,
    不难想到这题可以写深搜来做

    分析

    比如说以数据:

    3
    3 3 3
    

    为例子,
    进行了三场比赛:AB AC BC;
    我们只要搜索每场比赛,并枚举比赛的三个结果(胜、负、平)并判断能否达到答案的分数即可
    如果是三个人:

    void dfs(int step) {
    	if(step==cs+1){
    		int ff=1;
    		for(int i=1;i<=n;i++)
    			if(a[i]!=s[i]) ff=0;
    		if(ff)
    			ans++;
    		return;
    	}
    	int x=team3[step][0],y=team3[step][1];//team数组记录了每场比赛的两个参与者
    	if(s[x]+3<=a[x]){//结局1 A胜
    		s[x]+=3;
    		dfs3(step+1);
    		s[x]-=3;//回溯
    	}
    	if(s[y]+3<=a[y]){////结局2 B胜
    		s[y]+=3;
    		dfs3(step+1);
    		s[y]-=3;
    	}
    	if(s[x]+1<=a[x]&&s[y]+1<=a[y]){//结局3 平
    		s[x]++;
    		s[y]++;
    		dfs3(step+1);
    		s[y]--;
    		s[x]--;
    	}
    } 
    

    这样搜索的初步就算完成了

    然而分析一下时间复杂度

    由于我们搜索的是每一局比赛,每个比赛有三种结果,最多可能有(8*7/2)28场比赛,那么当n8时,时间复杂度为O(3^28(≈2.2e13)) 若不加剪枝肯定会T;

    所以要加上一些剪枝

    因为要求方案数,那么肯定最优化剪枝不行
    排序?似乎对本题求解没什么帮助
    而可行性剪枝在这里可以发挥出作用

    如果某个人在这局比赛后每次都赢,但是最终得分仍然低于期望得分,那么这个情况不存在,直接return

    还是以三个人为例

    上面的代码可以改成这样子:

    void dfs(int step) {
    	if(step==cs+1){
    		int ff=1;
    		for(int i=1;i<=n;i++)
    			if(a[i]!=s[i]) ff=0;
    		if(ff)
    			ans++;
    		return;
    	}
    	
    	for(int i=1;i<=n;i++){//剪枝
    		if(jz[n][i][step+1]*3+s[i]<a[i])//jz数组记录了总共n个人时第step场比赛后,还有几局比赛的机会(即胜利的可能)
    		return;
    	}
    	
    	int x=team3[step][0],y=team3[step][1];
    	if(s[x]+3<=a[x]){
    		s[x]+=3;
    		dfs3(step+1);
    		s[x]-=3;
    	}
    	if(s[y]+3<=a[y]){
    		s[y]+=3;
    		dfs3(step+1);
    		s[y]-=3;
    	}
    	if(s[x]+1<=a[x]&&s[y]+1<=a[y]){
    		s[x]++;
    		s[y]++;
    		dfs3(step+1);
    		s[y]--;
    		s[x]--;
    	}
    	
    } 
    

    其他的细节比如当n2||n1时可以直接输出
    还有team数组(可以再写一个test程序直接输出,不用手打):

    int team8[50][2]={{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{3,4},{3,5},{3,6},{3,7},{3,8},{4,5},{4,6},{4,7},{4,8},{5,6},{5,7},{5,8},{6,7},{6,8},{7,8}};
    int team7[50][2]={{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{2,3},{2,4},{2,5},{2,6},{2,7},{3,4},{3,5},{3,6},{3,7},{4,5},{4,6},{4,7},{5,6},{5,7},{6,7}};
    int team6[50][2]={{1,2},{1,3},{1,4},{1,5},{1,6},{2,3},{2,4},{2,5},{2,6},{3,4},{3,5},{3,6},{4,5},{4,6},{5,6}};
    int team5[50][2]={{1,2},{1,3},{1,4},{1,5},{2,3},{2,4},{2,5},{3,4},{3,5},{4,5}};
    int team4[50][2]={{1,2},{1,3},{1,4},{2,3},{2,4},{3,4}};
    int team3[50][2]={{1,2},{1,3},{2,3}};
    

    这样大概...就可以AC了吧

  • 相关阅读:
    Project2016下载安装密钥激活教程破解
    关于 Level 和 Promotion,其实就那么简单
    Docker 入门
    Spring Cloud Config中文文档
    如何合理设置线程池大小
    java中线程池的使用
    快速掌握和使用Flyway
    duilib教程之duilib入门简明教程6.XML配置界面
    duilib教程之duilib入门简明教程5.自绘标题栏
    duilib教程之duilib入门简明教程4.响应按钮事件
  • 原文地址:https://www.cnblogs.com/zhenglw/p/9507908.html
Copyright © 2011-2022 走看看