`
抛出异常的爱
  • 浏览: 629118 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

百度“变态比赛规则”算法题 java 的解法

阅读更多
没什么注释。。
作过的看看能不能再快一点
主题贴子在这里。。。。
http://www.iteye.com/post/307049
引用
变态比赛规则

为了促进各部门员工的交流,百度举办了一场全公司范围内的“拳皇”(百度内部最流行的格斗游戏)友谊赛,负责组织这场比赛的是百度的超级“拳皇”迷W.Z。W.Z不想用传统的淘汰赛或者循环赛的方式,而是自己制定了一个比赛规则。

由于一些员工(比如同部门或者相邻部门员工)平时接触的机会比较多,为了促进不同部门之间的交流,W.Z希望员工自由分组。不同组之间的每两个人都会进行一场友谊赛而同一组内的人之间不会打任何比赛。

比如4个人,编号为1~4,如果分为两个组并且1,2一个组,3,4一个组,那么一共需要打四场比赛:1 vs 3,1 vs 4,2 vs 3,2 vs 4。 而如

果是1,2,3一组,4单独一组,那么一共需要打三场比赛 1 vs 4,2 vs 4,3 vs 4。


很快W.Z意识到,这样的比赛规则可能会让比赛的场数非常多。W.Z想知道如果有N个人,通过上面这种比赛规则,总比赛场数有可能为K场吗?

比如3个人,如果只分到一组则不需要比赛,如果分到两组则需要2场比赛,如果分为三组则需要3场比赛。但是无论怎么分都不可能恰需要1场比赛。


相信作为编程高手的你一定知道该怎么回答这个问题了吧? 那么现在请你帮助W.Z吧。

package com.maodajun.javaeye1;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class BaiDuQuest {

	public String teamAndImpossable(int peoples,int impossable){
		int maximpossable= maxImpossable(peoples);
		maximpossable -=impossable;
		List list =selfTeam(peoples,maximpossable,new ArrayList());
		if(list!=null){
			return "YES";
		}
		return "NO";	
	}
	//递归算出最大可能。。。循环赛制
	public int maxImpossable(int poples){
		
		if(poples==2){
			return 1;
		}else if(poples<1){
			return 0;
		}
		poples--;
		return maxImpossable(poples)+poples;
	}
	
	public int maxFirstTeam(int peoples, int maximpossable){
		int tmp = 0 ;
		if(maxImpossable(peoples)<maximpossable){
			return -1;
		}
		for(int i = peoples ; i >1 ; i--){
			tmp = maxImpossable(i);
			if(tmp <= maximpossable){
				return i;
			}
		}
		return tmp;
	}
	public List selfTeam(int peoples , int maximpossable ,List list ){
		int max = maxFirstTeam(peoples,maximpossable);
		if(max==0){
			return list;
		}else if (max==-1){
			return null;
		}else{
			list .add(""+max);
			return selfTeam(peoples-max,maximpossable-maxImpossable(max),list);
		}	
	}
	public static  void main(String[] arg){
		BaiDuQuest quest = new BaiDuQuest();
		int people = 5;
		for(int i = quest.maxImpossable(people) ; i >=0; i--){
			List list =quest.selfTeam(people,i,new ArrayList());
			int count = 0 ;
			if(list!=null){
				for(int j = 0 ; j < list.size(); j ++){
					 count +=Integer.parseInt(list.get(j).toString());
					
				}
	
				list.add(""+(people-count));
			}
			System.out.println(quest.maxImpossable(people)-i+":"+list);
		}
	}
	 
	

}
分享到:
评论
60 楼 eboge 2007-06-21  
百度题见解:
N人分为m(0<m<=N)组,总比赛数用S代表,xi代表当前组的人数(注意:i是下标)
当m=1时,S=0;
当m=2时,S=(N-x)x;
当m=3时,S=(N-x0)x0+(N-x0-x1)x1
.....
当m时,S=(N-x0)x0+(N-x0-x1)x1+…+(N-x0-x1-…-x(m-2))x(m-2)
数学归纳法很容易证明
有了公式,再来解题就应该很容易了 ^_^
59 楼 williamy 2007-06-17  
如果是公平的比賽,淘汰率不可能高於一侷比賽淘汰一個這種效率,這種效率是固定的,就是1場比賽出局一個,或者3場比賽出局一個,或者。。。。。或者。。。。(1/2*n+1,n=0 1 2 3 4...),總之就是這個意思,意思是一場比賽,出局一個,沒見過別的更高效率的公平的比賽,當然你可以給那些比較猛的加一些權重,讓他們本身就有更高的優勢,既然你需要更高的淘汰率,那麽就直接來一個不公平的比賽嘍,隨便怎麽設定,根據個人喜好,你加多少料就加多少料,自助餐一樣哦,所以你可先排出一個1 2 3 4。。。來,然後先問前後兩個是否認可,認可就直接淘汰,不認可就打一侷,很簡單哦,很高效哦,很適合你們baidu的風格,這樣的效率zai 0.5--1之間,這麽牛的公司的這麽牛的問題,只適合這麽牛的回答,I think
58 楼 longrm 2007-06-14  
xmx111 写道
longrm 写道
解释解释了,这个代码很难懂滴


个人觉得注释得很清楚
以前他是没有注释的,后来加上的

自己写了段代码,只能找出一个解,以前学的动态规划都忘的差不多了,看来得找时间补补啦

import java.util.*;

public class Queen {
	private int chess[][] = new int[8][8];
	private int a[] = new int[8];
	private int b[] = new int[15];
	private int c[] = new int[15];
	private ArrayList colList = new ArrayList(); // 记录第i行皇后放置的列数
	
	// 占据位置i,j
	private void possess(int i, int j) {
		chess[i][j]=1;
		a[j]=1;
		b[i+j]=1;
		c[7+j-i]=1;
		colList.add(String.valueOf(j));
	}
	
	// 放弃
	private void giveUp(int i, int j) {
		chess[i][j]=0;
		a[j]=0;
		b[i+j]=0;
		c[7+j-i]=0;
		colList.remove(i);
	}
	
	// 判断位置i,j上是否可以被其他皇后攻击到
	private boolean isAttacked(int i, int j) {
		if(a[j]==1 || b[i+j]==1 || c[7+j-i]==1)
			return true;
		return false;
	}
	
	public void findPosition(int i, int j) {
		int col;
		if(i>7)
			return;
		if(j>7) {
			col = Integer.parseInt((String)colList.get(i-1));
			giveUp(i-1, col);
			col = Integer.parseInt((String)colList.get(i-2));
			giveUp(i-2, col);
			findPosition(i-2, col+1);
			return;
		}
		for(; j<8; j++) {
			if(!isAttacked(i, j)) {
				possess(i, j);
				findPosition(i+1, 0);
				return;
			}
		}
		col = Integer.parseInt((String)colList.get(i-1));
		giveUp(i-1, col);
		findPosition(i-1, col+1);
	}
	
	// 输出棋盘
	public void print() {
		for(int i=0; i<8; i++) {
			for(int j=0; j<8; j++)
				System.out.print(chess[i][j]+"---");
			System.out.println();
		}
	}
	
	public static void main(String[] args) {
		Queen q = new Queen();
		q.findPosition(0,0);
		q.print();
	}
}
57 楼 xmx111 2007-06-14  
longrm 写道
解释解释了,这个代码很难懂滴


个人觉得注释得很清楚
56 楼 抛出异常的爱 2007-06-13  
Eastsun 写道
呵呵,我在原来代码上做些注释吧...
ps:在这个贴讨论与主题无关的时,楼主会不会不高兴丫
不会的。。。
反正改一下题目就可以了。。。
55 楼 Eastsun 2007-06-12  
呵呵,我在原来代码上做些注释吧...
ps:在这个贴讨论与主题无关的时,楼主会不会不高兴丫
54 楼 longrm 2007-06-12  
解释解释了,这个代码很难懂滴
53 楼 Eastsun 2007-06-12  
楼上的链接打不开
52 楼 longrm 2007-06-12  
....

网速问题,延迟的厉害,偶还以为没提交呢,,,

你的代码我看看啦,不会再到这问你啦,嘿嘿
51 楼 Eastsun 2007-06-12  
在GCC下编译通过
ps:八皇后问题就是在8*8的棋盘中每行每列各放一个皇后,并使它们互不攻击
50 楼 Eastsun 2007-06-12  
算了,不测试了:
#include<stdio.h>
#include<conio.h>
#define NUM 8
int flags[NUM][NUM];      //这个用来记录已经摆好的棋子的影响的范围
char sets[NUM][NUM];      //这个用来记录那些位置摆了棋子

void check(int row,int col){
    int i,j;
    if(row>=NUM){//如果row>=NUM说明前8行都摆好了棋子,因此已经得到一个解
        for(i=0;i<NUM;i++){
            for(j=0;j<NUM;j++)
                printf(sets[i][j]?"*":"#");
            printf("\n");
        }
        printf("----------------------\n");
        return;
    }
    if(col>=NUM) return;    //这个说明这一行已经摆不下棋子了,无解,再往上回溯求解
    if(!flags[row][col]){   //flags[row][col]==0说明这个位置可以摆子
        i =1;
        while(i+row<NUM){   //将这个位置布子后所影响到的位置加1,注意,因为我们只需要知道对以后棋子的影响
                            //所以只对左下斜对角,列下,右下斜对角做了标记
            flags[i+row][col] ++;
            if(col+i<NUM) flags[i+row][i+col]++;
            if(col-i>=0)  flags[i+row][col-i]++;
            i++;
        }
        sets[row][col] =1;  //记录棋子位置
        check(row+1,0);     //因为这一行已经布好子,所以从下一行的开始位置开始check
        i =1;
        while(i+row<NUM){   //撤销上面做的标记
            flags[i+row][col] --;
            if(col+i<NUM) flags[i+row][i+col]--;
            if(col-i>=0)  flags[i+row][col-i]--;
            i++;
        }
        sets[row][col] =0;  //撤销棋子
    }
    check(row,col+1);       //继续试探这行的下一个位置
}
int main(){
    check(0,0);
    getch();
}
49 楼 抛出异常的爱 2007-06-12  
Eastsun 写道
==,writing
说写就能写出来哟。。。
PS什么叫八皇后的问题?
48 楼 Eastsun 2007-06-12  
==,writing
47 楼 longrm 2007-06-12  
Eastsun 写道
呵呵,楼上实际上是把我代码中关于动态规划的部分去掉了(就是保存计算结果的步聚).
但是这样效率会明显降低,因为里面做了很多重复计算.而动态规划由于保存了计算结果就避免了重复计算,
另一方面考虑到测试的时候是用多个测试数据,保存的计算结果就更能够提高效率了.

恩,偶知道的,你代码中那个BitSet就是来保存结果滴,偶这样写只是展示个最简单明了的过程啦

PS:你有没有八皇后的代码啊,贴一下啦(没有的话就临时做个好了,嘿嘿)
46 楼 Eastsun 2007-06-12  
呵呵,楼上实际上是把我代码中关于动态规划的部分去掉了(就是保存计算结果的步聚).
但是这样效率会明显降低,因为里面做了很多重复计算.而动态规划由于保存了计算结果就避免了重复计算,
另一方面考虑到测试的时候是用多个测试数据,保存的计算结果就更能够提高效率了.

45 楼 longrm 2007-06-12  
谁有八皇后的代码(最好将题目也贴出来),麻烦贴一下,谢谢
44 楼 longrm 2007-06-12  
引用
n个人能够比k场实际上是问: n能否存在一个分解 xi(xi>0)使得
Sum{xi} =n, Sum{xi*xj: i!=j} =k;

根据这个用递推可以非常简单的实现,下面是偶的代码,结果应该是对的,不知道性能能不能过

import java.util.*;

public class BaiduQuest {
	private ArrayList teamList; // 可以实现时保存分组情况
	private boolean solve;   // 保存是否可以实现
	
	public BaiduQuest(int n, int k) {
		teamList = new ArrayList();
		sum = 0;
		solve = isSolved(n, k);
	}
	
	// 递归解决是否可以实现
	public boolean isSolved(int n, int k) {
		if(n<=0) {
			System.out.println("Wrong number entered!");
			return false;
		}
		if(k<0 || k>n*(n-1)/2)
		  return false;
		else if(k==0) {
			teamList.add(n);
		  return true;
		}
		  
		for(int i=1; i<n; i++)
			if(isSolved(n-i, k-i*(n-i))){
				teamList.add(i);
				return true;
			}
			
		return false;
	}
	
	public void print() {
		System.out.println(String.valueOf(solve));
		
		// 输出分组情况
		for(int i=0; i<teamList.size(); i++)
		  System.out.println(teamList.get(i));
	}
	
	public static void main(String[] args) {
		// 直接在控制台获取数据n, k
		if(args.length!=2) {
		  System.out.println("Please enter right data!");
		  return;
		}
		BaiduQuest test = new BaiduQuest(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
		test.print();
	}
}
43 楼 抛出异常的爱 2007-06-12  
realreal2000 写道
写了个程序,不知道对不对,呵呵,不过计算比较麻烦,应该还能简单很多
public class Team {
	private int membercount;
	
	private int times;

	/**
	 * @return membercount
	 */
	public int getMembercount() {
		return membercount;
	}

	/**
	 * @param membercount 
	 */
	public void setMembercount(int membercount) {
		this.membercount = membercount;
	}

	/**
	 * @return times
	 */
	public int getTimes() {
		initTimes();
		return times;
	}

	private void initTimes() {
		times = (membercount*membercount-membercount)/2;		
	}

}

写了个算法
import java.util.*;

public class Match {
	private int totalcount;
	
	private int mostTimes;
	
	private int leastTimes;
	
	private int times;
	
	private int remaintimes;
	
	private List<Team> teams = new ArrayList();
	
	private int teamMemebers;

	/**
	 * @return leastTimes
	 */
	public int getLeastTimes() {
		return leastTimes;
	}

	/**
	 * @return mostTimes
	 */
	public int getMostTimes() {
		return mostTimes;
	}
	
	public Match(int totalcount){
		this.totalcount = totalcount;
		leastTimes = totalcount-1;
		mostTimes = countTimes(totalcount);
	}

	/**
	 * @return totalcount
	 */
	public int getTotalcount() {
		return totalcount;
	}
	
	public static int countTimes(int i){
		if(i==1)
			return 0;
		if(i==2)
		return 1;
		return (i*i-i)/2;
	}
	
	public boolean isCanPlay(){
		boolean result = false;
		if(times<leastTimes)
			return false;
		if(times>mostTimes)
			return false;
		if(times==leastTimes)
			return true;
		if(times==mostTimes)
			return true;
		while(remaintimes!=0){
			if(teamMemebers>totalcount)
				return false;
			createTeam(remaintimes);			
		}
		if(teamMemebers>totalcount)
			return false;
		return true;
	}
	
	public void createTeam(int m){
		Team team = new Team();
		if(m==1){
			team.setMembercount(2);
			teamMemebers = teamMemebers+2;
			teams.add(team);
			remaintimes = remaintimes-1;
			System.out.println("teamMemebers is "+teamMemebers);
			return;
		}
		int j = (m<=2)?5:2*m;
		for(int i =2;i<=j;i++){
			System.out.println("i is "+i);
			if(countTimes(i)>m){
				remaintimes = remaintimes-countTimes(i-1);
				teamMemebers = teamMemebers+i-1;
				System.out.println("teamMemebers is "+teamMemebers);
				team.setMembercount(i-1);
				return;
			}
		}
		teams.add(team);
	}

	/**
	 * @return times
	 */
	public int getTimes() {
		return times;
	}

	/**
	 * @param times 要设置的 times
	 */
	public void setTimes(int times) {
		this.times = times;
		System.out.println("mostTimes is "+mostTimes);
		this.remaintimes = this.mostTimes - times;
		System.out.println("remaintimes is "+remaintimes);
	}
	
	public static void main(String[] args){
		Match m = new Match(10);
		m.setTimes(32);
		try{
			if(m.isCanPlay()){
				System.out.println("Can");
			}else{
				System.out.println("Can not");
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}


把范围缩小
0到max
0+x到max+y
         int j = (m<=2)?5:2*m;  
         for(int i =2;i<=j;i++){  

这几行的魔术数字给卡住了。。
42 楼 抛出异常的爱 2007-06-11  
Eastsun 写道
longrm 写道
抛出异常的爱 写道
看了一下还真是看不明白呀。。。。
哈哈,偶都明白啦,就是那个计算的还没看出怎么算来的(主要是偶太懒了,嘿嘿)
虽然你的代码长多了,但效率不见得就比他的差,不知道怎么测试


呵呵,我不知道你还记得组合数么.
就是那个C(n,k),从n个元素里面取k个的方法数.

然后有个公式:  C(n+1,k+1) =C(n,k)+C(n,k+1)
(可以这样理解:从n+1个东西取k+1个,计某个元素为A,那么每种取法都属于下面的两种情形之一:
1:包含A ......相当于从另n个里面取k个
2:不包含A ....相当于从另n个里面取k+1个
从而有 C(n+1,k+1) =C(n,k)+C(n,k+1)
)

注意到 m*(m-1)/2 =C(m,2) =C(m+1,2+1) -C(m,2+1)(用了上面的公式)
从而:
                Sum{m*(m-1)/2 : 0<=m<=n-1}
             =  Sum{C(m+1,3)-C(m,3) :0<=m<=n-1}   (注意,抵消了很多)
             =  C(n,3) -C(0,3)
             =  C(n,3)
             =  n*(n-1)*(n-2)/3!


真精典,终于看明白了。。。
41 楼 抛出异常的爱 2007-06-11  
都差不多。。。。数学家分两种。
一种熟练把现实的问题用公式表现出来
另一种发现新的规率。。。。

相关推荐

    Java算法集题大全.zip

    Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法集题大全Java算法...

    java笔试常见的算法题

    全排序、二分查找、冒泡排序、阶乘、最大公约数、最小公倍数、...这是里面包含的算法,本人在准备笔试的时候找的,算法尽量采用最优的。 所有的代码均经过测试,个人觉得没有问题,如果哪位大牛找到错误,欢迎批评指正

    JAVA经典算法面试39题及答案

    本文将详细探讨39道JAVA经典算法面试题目,每题都附带答案和解析,从而帮助读者深入理解并提升自身在JAVA编程中的算法应用能力。 首先,我们必须明确算法的定义和重要性。算法是计算机科学的核心,它是一系列解决...

    java常见算法题解析大全。

    在这个“java常见算法题解析大全”中,你将找到一系列涵盖不同难度级别的算法问题,旨在帮助Java开发者提升技能,增强解决问题的能力。 首先,让我们了解一下折半查找(Binary Search)算法。这是一种在有序数组中...

    C++牛客比赛算法题,很好的学习资源!

    C++牛客比赛算法题,很好的学习资源! C++牛客比赛算法题,很好的学习资源! C++牛客比赛算法题,很好的学习资源! C++牛客比赛算法题,很好的学习资源! C++牛客比赛算法题,很好的学习资源! C++牛客比赛算法题,...

    华为od算法题-最多提取子串数目-Java解法

    华为od算法题,100分题-最多提取子串数目-Java解法

    JAVA算法编程题目及答案.doc

    JAVA算法编程题目及答案 本资源提供了50道JAVA算法编程题目及答案,涵盖了算法设计、数据结构、程序设计等多个方面的知识点。以下是对标题、描述、标签和部分内容的详细解释: 标题:JAVA算法编程题目及答案 本...

    百度java面试查找算法代码

    本题目的核心是一个经典的查找问题,它出现在百度的面试环节中,目的是考察候选人的逻辑思维和算法实现能力。下面将详细讨论这个问题以及提供的三种解决方案。 题目描述了一个数字序列,包含从1到1000的999个乱序的...

    java经典算法练习题

    本压缩包包含了三个文档,分别是“JAVA经典算法40题.doc”、“最新JAVA编程题全集_50题及答案.doc”和“50道JAVA基础编程练习题.doc”,这些资源为初学者提供了大量的实践机会,有助于深入理解和运用Java。...

    java算法题(四)

    java算法题 java算法题 java算法题 java算法题java算法题

    JAVA算法编程题汇总(50题及答案)

    Java 算法编程题汇总 Java 算法编程题汇总是本文的主题,本文将对 50 道 Java 算法编程题进行汇总,涵盖了 Fibonacci 序列、素数、水仙花数、质因数分解等多个方面的知识点。 Fibonacci 序列 Fibonacci 序列是...

    几个推荐算法的java实现

    本项目提供了一些推荐算法的Java实现,包括slopeone、SVD(奇异值分解)以及基于物品邻接的SVD(ItemNeighborSVD)。下面我们将详细探讨这些算法及其在Java中的实现。 1. **slopeone**: - Slope One是一种简单的...

    道格拉斯-普克抽稀算法,java 实现

    道格拉斯-普克抽稀算法,java 实现

    JAVA基础编程练习题50题及经典算法90题【含源码及答案】-史上最全

    Java基础编程练习题和经典算法是提升编程技能和准备面试的关键环节。这50题的基础编程练习涵盖了Java语言的核心概念,如数据类型、控制结构、类与对象、异常处理、集合框架等,旨在帮助学习者巩固基础知识并提高编程...

    电梯调度算法(java实现)

    在这个Java实现中,我们将深入探讨电梯调度算法的基本原理、常见策略以及如何在Java编程环境中进行模拟。 电梯调度算法的核心目标是有效地服务楼层数字上的请求,以减少乘客的等待时间和电梯的移动距离。这个过程...

    祖冲之密码算法Java实现

    9. **性能优化**:虽然祖冲之算法本身已经设计得很高效,但在Java中实现时,仍需要注意内存管理和计算性能,以适应可能的大规模数据加密需求。 10. **文档编写**:为了方便其他开发者理解和使用你的实现,需要编写...

    数据结构与算法分析(Java语言描述)习题答案(第三版).docx

    在《数据结构与算法分析(Java语言描述)》(第三版)这本教材中,我们看到涉及了关于数据结构、算法以及程序设计的基础概念。在给出的文档中,部分题目和答案涵盖了递归、数学推理、文件处理以及计算理论等多个方面...

    JAVA经典算法90题【含源码】

    "JAVA经典算法90题【含源码】"的资源集合为Java初学者提供了一个绝佳的学习平台,旨在通过实际操作来理解和应用各种基础及进阶算法。下面将详细阐述这些算法题目所涉及的知识点,并建议的学习路径。 首先,"JAVA...

    java经典算法 java经典算法

    在Java编程语言的浩瀚世界中,掌握一些经典的算法对于任何开发者来说都是一项宝贵的能力。这些算法不仅能够帮助我们解决特定的编程问题,而且能够锻炼我们的逻辑思维能力和编程技巧。通过研究和实现这些算法,我们...

Global site tag (gtag.js) - Google Analytics