ZOJ 3879 — Capture the Flag

原题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3879

题意:输入四个数n q s c ,n — 有n个队伍,q — 有q个服务器,s — 每个队伍的初始分数,c — 有c个操作;

    对于每次操作,先输入一个数k,接下来k行,每行输入三个数a b c,表示a通过服务器c成功攻击了b;

对于每次的成功攻击,b都会减少n-1分,这n-1分会平分给通过同一个服务器攻击b的队伍;

接下来q行,每行n个数,1表示成功修复,0表示未修复;

未修复的队伍会减少n-1分,这n-1分平分给修复成功的队伍;

然后输入m个数,询问这m个队伍的分数以及排名;


#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>

using namespace std;
#define exp 1e-5
bool vis[110][110][110];
bool vic[110];

struct node
{
	int id, rank;
	double score;
}w[110];

bool cmp1(node x, node y)
{
	return x.score>y.score;
}

bool cmp2(node x, node y)
{
	return x.id<y.id;
}

int main()
{
	int cas;
	scanf("%d", &cas);
	while(cas--)
	{
		double s;
		int n, q, c;
		scanf("%d%d%lf%d", &n, &q, &s, &c);
		for(int i = 1;i<=n;i++)
		{
			w[i].id = i;
			w[i].rank = 1;
			w[i].score = s;
		}
		while(c--)
		{
			int k;
			scanf("%d", &k);
			memset(vis, false, sizeof(vis));
			while(k--)
			{
				int a, b, c;
				scanf("%d%d%d", &a, &b, &c);
				vis[a][b][c] = true;
			}
			for(int t = 1;t<=q;t++)
			{
				for(int j = 1;j<=n;j++)
				{
					int con = 0;
					for(int i = 1;i<=n;i++)
					{
						if(vis[i][j][t])
						con++;
					}
					if(con == 0)
					continue;
					w[j].score-=(n-1);
					double val = 1.0*(n-1)/con;
					for(int r = 1;r<=n;r++)
					{
						if(vis[r][j][t])
						w[r].score+=val;
					}
				}
			}
			
			for(int i = 1;i<=q;i++)
			{
				memset(vic, false, sizeof(vic));
				int con = 0;
				for(int j = 1;j<=n;j++)
				{
					int x;
					scanf("%d", &x);
					if(!x)
					{
						w[j].score-=(n-1);
						vic[j] = true;
						con++;
					}
				}
				if(con == n)
				continue;
				double val = 1.0*(n-1)*con/(n-con);
				for(int t = 1;t<=n;t++)
				{
					if(!vic[t])
					w[t].score+=val;
				}
			}
			
			sort(w+1, w+n+1, cmp1);
			for(int i = 1;i<=n;i++)
			{
				if(i!=1)
				{
					if(fabs(w[i].score-w[i-1].score)<exp)
	                w[i].rank = w[i-1].rank;
	                else
                	w[i].rank = i;
				}
                else
                w[i].rank = i;
			}
			sort(w+1, w+n+1, cmp2);
			int m;
			scanf("%d", &m);
			while(m--)
			{
				int x;
				scanf("%d", &x);
				printf("%f %d\n", w[x].score, w[x].rank);
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值