模拟:
请仔细读题
队伍的某个服务器被攻击 会扣 n-1 分 分数分给攻击该服务器的队伍
若一个队的第i个服务器不能维持,则会扣去n-1分,分给其他第 i 个服务器还能维持的队伍
(每次checkpoint服务器状态都是1)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
#include <cmath>;
using namespace std;
#define ll long long
struct node
{
int id,rank;
double fenshu;
}man[1000];
bool cmp0(node a,node b)
{
return a.fenshu>b.fenshu;
}
bool cmp1(node a,node b)
{
return a.id<b.id;
}
int n,q,s,c;
int vis[105][105][105],visnum[105][105];
int ser[106];
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>q>>s>>c;
for(int i=1;i<=n;i++)
{
man[i].id=i;
man[i].rank=1;
man[i].fenshu=s;
}
int x;
while(c--)
{
scanf("%d",&x);
memset(vis,0,sizeof(vis));
memset(visnum,0,sizeof(visnum));
while(x--)//攻击
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(vis[a][b][c]) continue;
vis[a][b][c]=1;
visnum[b][c]++;
}
for(int i=1;i<=n;i++)//枚举人
{
for(int k=1;k<=q;k++)//枚举服务器
{
if(visnum[i][k])
{
double d=1.0*(n-1.0)/visnum[i][k];
for(int j=1;j<=n;j++)//枚举攻击者
{
if(vis[j][i][k])
{
man[j].fenshu+=d;
}
}
man[i].fenshu-=n-1;
}
}
}
//
for(int i=1;i<=q;i++)
{
int ans=0;
for(int j=1;j<=n;j++)
{
scanf("%d",&ser[j]);
if(ser[j]==0) ans++;
}
if(ans==0) continue; //ans 表示 不能维持的个数
double c=ans*1.0*(n-1.0)/(n-ans);
for(int j=1;j<=n;j++)
{
if(ser[j]==0)
{
man[j].fenshu-=n-1;
}
else
man[j].fenshu+=c;
}
}
sort(man+1,man+1+n,cmp0);
man[1].rank=1;
for(int i=2;i<=n;i++)
{
if(man[i-1].fenshu-man[i].fenshu<0.00001)
man[i].rank=man[i-1].rank;
else man[i].rank=i;
}
sort(man+1,man+1+n,cmp1);
int x,b;
scanf("%d",&x);
for(int i=0;i<x;i++)
{
scanf("%d",&b);
printf("%.8lf %d\n",man[b].fenshu,man[b].rank);
}
}
}
return 0;
}
/*
*/