ZOJ 3879 Capture the Flag (浙江省省省赛K题+模拟)

ZOJ 3879 Capture the Flag (浙江省省赛K题+模拟)

题目链接:ZOJ 3879 Capture the Flag

题意:给出n支队伍互相攻击服务器,有以下规则:

1.如果A队的服务器1被B队攻击成功,A队将失去n-1点分数,这n-1点分数会平分给成功攻击A队的服务器1的其他队伍。

eg:

共4个队

A B 1

C B 1

此时A队和C队都获得1.5(3/2)分,B队失去3分

2.如果一个队不能维护好他们的服务器,该队将失去n-1分,这n-1分平分给其他能维护好服务器的队伍。

eg:

1 1 0 1

0 1 1 1

针对服务器1(即第一行),只有C队没维护好,所以C队失去3分,A,B,D队各获得1(3/3)分。

针对服务器2(即第二行),只有A队没维护好,所以A队失去3分,C,B,D队各获得1(3/3)分。


输出c场比赛中每场比赛询问队伍的分数和排名。


注意:即使每个服务器被攻击多次,结算分数时只算一次。


AC代码:

#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
const double ep=1e-5;
bool vis[110][110][110];
bool cvis[110][110];

struct node{
	double p;
	int id,rank;
};
struct node pp[110];
double p[110];
int Rank[110];

bool cmp(node a,node b){
	return a.p>b.p;
}

bool cmp2(node a,node b){
	return a.id<b.id;
}
void getRank(double arr[],int n){
	int i;
	for(i=1;i<=n;i++){
		pp[i].id=i;
		pp[i].p=arr[i];
	}
	sort(pp+1,pp+n+1,cmp);
	int r=1;
	pp[1].rank=r;
	r++;
	for(i=2;i<=n;i++){
		if(pp[i-1].p-pp[i].p<=ep)
			pp[i].rank=pp[i-1].rank;
		else pp[i].rank=r;
		r++;
	}
	for(i=1;i<=n;i++)
		Rank[pp[i].id]=pp[i].rank;
}

int main()
{
	int t;
	int n,q,s,c;
	int a,i,j;
	int u,v,w,k;
	scanf("%d",&t);
	while(t--){
		scanf("%d %d %d %d",&n,&q,&s,&c);
		for(i=1;i<=n;i++){
			p[i]=s*1.0;
			Rank[i]=1;
		}
		while(c--){
			memset(vis,false,sizeof vis);
			memset(cvis,false,sizeof cvis);
			scanf("%d",&a);
			for(i=0;i<a;i++){
				scanf("%d %d %d",&u,&v,&w);
				cvis[v][w]=true;
				vis[u][v][w]=true;
			}
			int count=0;
			//被攻击的j队,k服务器
			for(j=1;j<=n;j++){
				for(k=1;k<=q;k++){
					count=0;
					for(i=1;i<=n;i++)
						if(vis[i][j][k]) count++;
					if(count==0) continue; 
					for(i=1;i<=n;i++)
						if(vis[i][j][k]) p[i]+=(n-1)*1.0/count;
				}
				count=0;
				for(k=1;k<=q;k++)
					if(cvis[j][k]) p[j]-=(n-1);
			}
			int st;
			bool vvis[110];
			for(i=1;i<=q;i++){
				count=0;
				for(j=1;j<=n;j++){
					vvis[j]=false;
					scanf("%d",&st);
					if(!st) count++;// not work well 
					else vvis[j]=true;
				}
				if(count==0) continue;
				for(j=1;j<=n;j++){
					if(!vvis[j]) p[j]-=(n-1);
					else p[j]+=(n-1)*count*1.0/(n-count);
				}
			}
			getRank(p,n);
			scanf("%d",&u);
			while(u--){
				scanf("%d",&v);
				printf("%.8lf %d\n",p[v],Rank[v]);
			}
		}
	}
	return 0;
}
/*

1
4 2 2500 5
0
1 1 1 1
1 1 1 1
4
1 2 3 4

2
1 2 1
3 2 1
1 1 1 1
1 1 1 1
4
1 2 3 4

1
1 2 2
1 1 1 1
1 1 1 0
4
1 2 3 4

0
0 0 0 0
0 0 0 0
4
1 2 3 4

0
1 1 1 1
1 1 1 1
2
1 4

2500.00000000 1
2500.00000000 1
2500.00000000 1
2500.00000000 1

2501.50000000 1
2497.00000000 4
2501.50000000 1
2500.00000000 3

2505.50000000 1
2495.00000000 4
2502.50000000 2
2497.00000000 3

2499.50000000 1
2489.00000000 4
2496.50000000 2
2491.00000000 3

2499.50000000 1
2491.00000000 3
*/