NWERC 2012 Foul Play 构造 (uvaLive 6271 )


书上的解法:

每一轮分四个阶段:

第一阶段:对队1不能消灭的队伍,尽量用队1能消灭的队伍去消灭。

第二阶段:队1任选一个能战胜的队伍 消灭。

第三阶段: 队1不能消灭的队伍自相残杀。

第四阶段:所有未比赛的队伍任意杀。


这样每一轮结束之后都能保证队1至少能战胜一半的队伍。



代码写的烂,只能给自己以后看看。



#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define rep(i,n)  for(int i=0 ;i<(n) ;i++)
using namespace std;
typedef long long ll;
const int INF =0x3f3f3f3f;
const int maxn=1024    ;
int n;
char s[maxn+10];
bool win[maxn+10][maxn+10];
bool vis[maxn+10];
bool done[maxn+10];
void read()
{
    memset(done,0,sizeof done);
     for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for(int j=1;j<=n;j++)
        {
            win[i][j]= s[j]=='1'?1:0;
        }
    }
}


void match()
{
    memcpy(vis,done,sizeof done);


    for(int i=2;i<=n;i++)  if(!vis[i]&&!win[1][i])
    {
        int find=-1;
        for(int j=1;j<=n;j++)  if(!vis[j]&&win[1][j]&&win[j][i])//最中间那个条件很重要
        {
            find=j;
            break;
        }
        if(~find)
        {
            vis[i]=1;
            done[i]=1;
            vis[find]=1;
            printf("%d %d\n",find,i);
        }

    }


    for(int i=1;i<=n;i++)  if(!vis[i]&&win[1][i])
    {
        done[i]=1;
        vis[i]=1;
        vis[1]=1;
        printf("%d %d\n",1,i);
       break;
    }

    int now=-1;
    for(int i=1;i<=n;i++)   if(!vis[i]&&!win[1][i])
    {
        if(now==-1)
        {
            now=i;
        }
        else
        {
            printf("%d %d\n",now,i);
            vis[now]=vis[i]=1;
            if(win[now][i])  done[i]=1;
            else          done[now]=1;

            now=-1;
        }
    }


    if(~now)
    {
        for(int i=1;i<=n;i++)  if(!vis[i]&&i!=now)
        {
             printf("%d %d\n",now,i);
            vis[now]=vis[i]=1;
            if(win[now][i]) done[i]=1;
            else        done[now]=1;
            break;
        }

        now=-1;
    }

    for(int i=1;i<=n;i++)  if(!vis[i])
    {
        if(now==-1)
        {
            now=i;
        }
        else
        {
            printf("%d %d\n",now,i);
             vis[now]=vis[i]=1;
           if(win[now][i])  done[i]=1;
            else      done[now]=1;
             now=-1;
        }
    }

}

void work()
{
    int num=n;
    while(num>1)
    {
        match();
        num/=2;
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        read();
        work();
    }

   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值