题意:按照题目模拟。
题记:需要注意一下最后判断两个队伍分数是否相同时不能用==,不然会有误差导致WA。
#include<bits/stdc++.h>
using namespace std;
const int N=105;
const double eps=1e-7;
struct Node{
int id;
double sum;
int ranks;
}a[N];
bool vis[N][N][N];
bool cmp1(Node x,Node y){
return x.sum>y.sum;
}
bool cmp2(Node x,Node y){
return x.id<y.id;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,q,c;
double s;
scanf("%d%d%lf%d",&n,&q,&s,&c);
for(int i=1;i<=n;i++){//赋值
a[i].id=i;
a[i].sum=s;
a[i].ranks=1;
}
while(c--){
int t;
memset(vis,0,sizeof(vis));
scanf("%d",&t);
while(t--){//攻击次数
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
vis[x][y][z]=1;
//第x个人攻击第y个人各第z个服务器
}
for(int i=1;i<=q;i++){//枚举服务器
for(int j=1;j<=n;j++){//枚举被攻击的队伍
int cnt=0;
for(int k=1;k<=n;k++){//枚举攻击队伍
if(vis[k][j][i])
cnt++;//记录有多少个队伍攻击了j的第i个服务器
}
if(!cnt) continue;
//没有队伍攻击
a[j].sum-=n-1;
double xx=(n-1)*1.0/cnt;
//每支队伍分到的分数
for(int k=1;k<=n;k++){
if(vis[k][j][i])
a[k].sum+=xx;//加上分数
}
}
}
for(int i=1;i<=q;i++){
vector<int>a1;//1
vector<int>a2;//0
int xx;
for(int j=1;j<=n;j++){
scanf("%d",&xx);
if(xx)a1.push_back(j);
else a2.push_back(j);
}
double tmp=0;
for(int j=0;j<a2.size();j++){
a[a2[j]].sum-=n-1;
tmp+=n-1;
}
tmp=1.0*tmp/a1.size();
for(int j=0;j<a1.size();j++){
a[a1[j]].sum+=tmp;
}
}
int u;
scanf("%d",&u);
sort(a+1,a+1+n,cmp1);//按照分数排序
int f=0;
for(int i=1;i<=n;i++){
f++;
if(i==1)
a[i].ranks=f;
else if(fabs(a[i].sum-a[i-1].sum)<eps)
a[i].ranks=a[i-1].ranks;
else
a[i].ranks=f;
}
sort(a+1,a+1+n,cmp2);//按照id排序
while(u--){
int p;
scanf("%d",&p);
printf("%.8f %d\n",a[p].sum,a[p].ranks);
}
}
}
return 0;
}