【Poj1818】ATP 二分+贪心

来源:互联网 发布:e63诺基亚软件下载网址 编辑:程序博客网 时间:2024/06/04 19:16

蛮有意思的一道题。。。

题目大意:2^n次方个人打淘汰赛,每个人有一个确定的名次(没有重复),如果两个人的名词在k之内那么谁都可以赢,否则一定是名次靠前的那个人赢,问经过n轮淘汰赛,最终获胜的那个人的最低名次是多少。

二分最低名次,倒着模拟整个过程,每一轮比赛每个人将自己能打败的最强对手打败,检查最后是否能复原即可。

#include<cstdlib>#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<vector>using namespace std;int n,k,c;bool v[2][5005];int hh=1;bool check(int x){memset(v,0,sizeof(v));hh=n;v[1][x]=true;for(int i=1;i<=c;i++){for(int j=1;j<=n;j++)v[(i+1)%2][j]=v[i%2][j];for(int j=1;j<=n;j++)if(v[i%2][j]){bool flag=false;for(int u=max(1,j-k);u<j;u++){if(!v[(i+1)%2][u]){flag=true;v[(i+1)%2][u]=true;break;}}if(!flag){for(int u=j+1;u<=n;u++){if(!v[(i+1)%2][u]){flag=true;v[(i+1)%2][u]=true;break;}}}if(!flag)return false;}}return true;}void work(){int l=1,r=n,mid,ans=0;while(l<=r){mid=(l+r)>>1;if(check(mid)){ans=mid;l=mid+1;}else{r=mid-1;}}printf("%d\n",ans);return ;}int main(){//freopen("in.txt","r",stdin);scanf("%d%d",&n,&k);for(int i=0;;i++){if((1<<i)==n){c=i; break;}}work();return 0;}

0 0
原创粉丝点击