Description 现在我们手里有一张2维的正整数(包括0)表.对于第i行第j列的那个数我们有如下定义:a[i][j]是 a[i][k]{其中0<=k<j}和a[k][j]{其中0<=k<i}没有出现的那个最小的正整数比如a[0][0]=0;Input有多组测试数据 每组数据一行,包括两个数:x,y,{x,y都是int型的正整数(包括0)}.Output输出每行一个整数, 即要找的这个数a[x][y].
Sample Input0 00 11 01 1
Sample Output0110 Authorfgjlwj
递归分治算法 -循环赛程表
PS:第一次用学着数据结构与算法上的循环赛日程表,用二维矩阵打表,不过显然的MLE,后来自己画画图找找规律。于是就搞定了。
因为是以2次方的增长,每次递归数据规模就/2,所以int型的数据不用几次也可以求得答案。
循环赛日程表
设有n=2^k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表。
(1)每个选手必须与其他n-1个选手各赛一次。
(2)每个选手一天只能赛一次。
(3)循环赛一共进行n-1天。
按此要求可将比赛日程表设计成有n行和n-1列的表。在表中第i行和第j列处填入第i个选手在第j天所遇到的选手。
按分治测率,可以将所有选手对分成两半,n个选手的比赛日程表就可以通过为n/2个选手设计的比赛日程表来决定。递归的用这种一分为二的策略对选手进行分割,知道只剩下两个选手时,比赛日程表的指定就变得很简单了。这时只要让这两个选手技能型比赛就可以了。
k=1 k=2 k= 3
1 2 1 2 | 3 4 .........对称关系
2 1 2 1 | 4 3
3 4 | 1 2
4 3 | 2 1
/*
Satan2868C++ (G++-3)Accepted660ms592KB */#include<iostream>#include<cstring>#include<cstdlib>using namespace std;
int f(int x,int y){ /* 递归结束条件 */ if(x==1&&y==1) return 1; if(x==1&&y==2) return 2; if(x==2&&y==1) return 2; /* 判断x,y的位置 */ int temp; int sum1 = 0,sum2 = 0; int key; temp = 2; while(temp<x) { temp *= 2; sum1++; } temp = 2; while(temp<y) { temp *= 2; sum2++; } /* 递归右下方 */ if(sum1==sum2) { key = 1<<sum1; return f(x-key,y-key); } /* 递归右上方 */ else if(sum1<sum2) { key = 1<<sum2; return f(x,y-key)+key; } /* 递归左下方 */ else { key = 1<<sum1; return f(x-key,y)+key; }}
int main(){ int x,y; while(scanf("%d %d",&x,&y)==2) { printf("%d/n",f(x+1,y+1)-1); } return 0;}