记录编号 609804 评测结果 A
题目名称 4223.[THUPC 2018] 组合数问题 最终得分 100
用户昵称 GravatarLikableP 是否通过 通过
代码语言 C++ 运行时间 4.421 s
提交时间 2025-11-26 16:18:41 内存使用 26.40 MiB
显示代码纯文本
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<string>
#include<iostream>

using namespace std;

const int maxn=110;
const int maxk=210;
const int maxr=1010;
const long double eps=1e-8;

int n,m,k,R,h;

int map[maxn][maxn];

int x[maxk],y[maxk];

int a[maxk],b[maxk],c[maxk],d[maxk];

int f[maxk],z[maxk],r[maxk],s[maxk];

int v[maxk],o[maxk],l[maxk];

int nown[maxk],nowm[maxk],skillable[maxk],bombed[maxk],dead[maxk];

int id[maxk];

int history[maxr][maxk][9];

int dx[4],dy[4];

int q[2][maxk];

int lastp;

int result[maxk];

bool use[maxk];

long double fac[1000010];

queue<int> enforce[maxk];

int get_num_of_skill(string s)
{
	if (s == "toolihai") return 1;
	if (s == "faceking") return 2;
	if (s == "onepunch") return 3;
	if (s == "rabiribi") return 4;
	if (s == "firework") return 5;
	if (s == "viuganda") return 6;
	if (s == "2dsaigao") return 7;
	if (s == "gugugugu") return 8;
	if (s == "backward") return 9;
	if (s == "hupraise") return 10;
	return -100;
}

int sign(long double l)
{
	if (fabsl(l)<=eps) return 0;
	if (l<0) return -1;
	else return 1;
}

int dis(int i,int j)
{
	return abs(x[i]-x[j])+abs(y[i]-y[j]);
}

void init_one(int i)
{
	nown[i]=a[i];
	nowm[i]=b[i];
	skillable[i]=0;
	bombed[i]=0;
	while (enforce[i].size())
		enforce[i].pop();
	dead[i]=0;
}

void init()
{
	scanf("%d%d%d%d",&n,&m,&k,&R);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			scanf("%d",&map[i][j]);
	for (int i=1;i<=k;i++)
	{
		scanf("%d%d",&x[i],&y[i]);
		scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
		scanf("%d%d",&f[i],&z[i]);
		scanf("%d",&r[i]);

		string name;
		cin>>name;
		s[i]=get_num_of_skill(name);

		if (s[i] == 1) {
		} else if (s[i] == 2){
		} else if (s[i] == 3) {
			scanf("%d%d",&v[i],&l[i]);
		} else if (s[i] == 4) {
			scanf("%d",&v[i]);
		} else if (s[i] == 5) {
			scanf("%d",&l[i]);
		} else if (s[i] == 6) {
		} else if (s[i] == 7) {
			scanf("%d%d%d",&o[i],&v[i],&l[i]);
		} else if (s[i] == 8) {
		} else if (s[i] == 9) {
			scanf("%d",&l[i]);
		} else if (s[i] == 10) {
		}
		else {
			//fprintf(stderr,"wang yu zhong tian xia wu di, yang jing qin ye ye sheng hui.\n");
		}

		init_one(i);
	}

	for (int i=0;i<=n+1;i++)
		map[i][0]=map[i][m+1]=1;
	for (int i=0;i<=m+1;i++)
		map[0][i]=map[n+1][i]=1;

	lastp = 0;
}

void respawn(int i)
{
	//fprintf(stderr,"%d respawns\n",i);
	init_one(i);
}

void recover() {
	//fprintf(stderr,"recover begin\n");
	for (int i=1;i<=k;i++)
	{
		if (dead[i]>0) 
		{
			dead[i]--;
			if (!dead[i]) respawn(i);
		}
		if (f[i]>0) f[i]--;
		if (skillable[i]>0) skillable[i]--;
		if (bombed[i]>0) bombed[i]--;
		while (enforce[i].size()>0) 
		{
			int fv = enforce[i].front();
			if (fv == h)
			{
				enforce[i].pop();
				nown[i] = max(nown[i]-v[i],0);
				nowm[i] = min(nowm[i],max(nown[i]-v[i],0));
				//fprintf(stderr,"%d enforce disappears, back to (%d,%d)\n",i,nown[i],nowm[i]);
			}
			else break;
		}
	}
}

void log()
{
	for (int i=1;i<=k;i++)
	{
		history[h][i][0] = h;
		history[h][i][1] = x[i];
		history[h][i][2] = y[i];
		history[h][i][3] = d[i];
		history[h][i][4] = nown[i];
		history[h][i][5] = nowm[i];
		history[h][i][6] = dead[i];
		history[h][i][7] = bombed[i];
		history[h][i][8] = skillable[i];
	}
}

void move() {
	//fprintf(stderr,"move begins\n");	
	for (int i=1;i<=k;i++)
		if (!bombed[i] && !dead[i])
		{
			int xx=x[i]+dx[d[i]];
			int yy=y[i]+dy[d[i]];
			if (map[xx][yy])
			{
				d[i]=d[i]^1;
				//fprintf(stderr,"%d turns at (%d,%d)\n",i,x[i],y[i]);
			}
			else
			{
				//fprintf(stderr,"%d moves from (%d,%d) to (%d,%d)\n",i,x[i],y[i],xx,yy);
				x[i]=xx;
				y[i]=yy;
			}
		}
}

bool dfs(int now)
{
	for (int i=1;i<=k;i++)
		if (c[i] && ((nown[i]^nown[now])%3==0) && !use[i])
		{
			use[i]=true;
			if (!result[i] || dfs(result[i]))
			{
				result[i]=now;
				return true;
			}
		}
	return false;
}

void matching()
{
	int ans=0;
	memset(result,0,sizeof(result));
	for (int i=1;i<=k;i++)
		if (!c[i])
		{
			memset(use,false,sizeof(use));
			if (dfs(i)) ans++;
		}
	printf("%d\n",ans);
}

bool check_in(int j,int i)
{
	int ndx = x[j]-x[i];
	int ndy = y[j]-y[i];
	if (d[i] == 0) ndx=-ndx;
	else if (d[i] == 2)
	{
		ndy = -ndy;
		swap(ndx,ndy);
	}
	else swap(ndx,ndy);
	return ndx >= 1 && ndx <= v[i] && ndy >= -ndx && ndy <= ndx;
}

void skill() {
	//fprintf(stderr,"skill begin\n");
	bool skip[2] = {false,false};
	for (int i=1;i<=k;i++)
		if (!f[i] && !skillable[i] && !skip[c[i]] && !dead[i])
		{
			//fprintf(stderr,"%d use skills %d\n",i,s[i]);
			f[i]=z[i];
			if (s[i] == 1) {
				lastp = i;
			} else if (s[i] == 2){
				for (int j=1;j<=k;j++)
					if (!dead[j])
					{
						if (d[j] == 0) d[j]=2;
						else if (d[j] == 1) d[j]=3;
						else if (d[j] == 2) d[j]=1;
						else d[j]=0;
					}
			} else if (s[i] == 3) {
				enforce[i].push(h+l[i]);
				nown[i] += v[i];
				//fprintf(stderr,"enforce to (%d,%d)\n",nown[i],nowm[i]);
			} else if (s[i] == 4) {
				for (int j=1;j<=k;j++)
					if (check_in(j,i))
					{
						//fprintf(stderr,"%d is knoced from (%d,%d) to",j,x[j],y[j]);
						x[j] += dx[d[i]];
						y[j] += dy[d[i]];
						while (map[x[j]][y[j]])
						{
							if (!x[j]) x[j]=n;
							else if (x[j]==n+1) x[j]=1;
							else if (!y[j]) y[j]=m;
							else if (y[j]==m+1) y[j]=1;
							else {
								x[j] += dx[d[i]];
								y[j] += dy[d[i]];
							}
						}
						//fprintf(stderr," (%d,%d)\n",x[j],y[j]);
					}
			} else if (s[i] == 5) {
				if (lastp) bombed[lastp] += l[i];
				else bombed[i] += l[i];
			} else if (s[i] == 6) {
				int maxp=0,minp=0;
				for (int j=1;j<=k;j++)
					if (dead[j])
					{
						int distance = dis(i,j);
						if (c[i] == c[j])
						{
							if (!maxp || distance>=dis(maxp,i)) maxp=j;
						}
						else
						{
							if (!minp || distance<=dis(minp,i)) minp=j;
						}
					}
				if (maxp) respawn(maxp);
				else if (minp) respawn(minp);
			} else if (s[i] == 7) {
				int nx = x[i];
				int ny = y[i];
				int ndx = dx[d[i]], ndy = dy[d[i]];
				if (d[i] == 0) ndy = 1;
				else if (d[i] == 1) ndy = -1;
				else if (d[i] == 2) ndx = -1;
				else ndx = 1;
				for (int j=1;j<=o[i];j++)
				{
					int nnx = nx + ndx;
					int nny = ny + ndy;
					if (map[nnx][nny])
					{
						ndx = ndy;
						ndy = -ndx;
						nnx = nnx + ndx;
						nny = nny + ndy;
						nnx = (nnx+nx) / 2;
						nny = (nny+ny) / 2;
						if (map[nnx][nny])
						{
							ndx = ndy;
							ndy = -ndx;
						}
						else
						{
							nx = nnx;
							ny = nny;
						}
					}
					else
					{
						nx = nnx;
						ny = nny;
					}
				}
				x[0]=nx;y[0]=ny;
				//fprintf(stderr,"bomed at (%d,%d)\n",x[0],y[0]);
				for (int j=1;j<=k;j++)
					if (dis(0,j)<=v[i]) 
					{
						skillable[j]+=l[i];
						//fprintf(stderr,"effect %d\n",j);
					}
			} else if (s[i] == 8) {
				skip[c[i]] = true;
			} else if (s[i] == 9) {
				int j = h-l[i];
				x[i]=history[j][i][1];
				y[i]=history[j][i][2];
				d[i]=history[j][i][3];
				nown[i]=history[j][i][4];
				nowm[i]=history[j][i][5];
				dead[i]=history[j][i][6];
				bombed[i]=history[j][i][7];
				skillable[i]=history[j][i][8];
				//fprintf(stderr,"%d jumps back to %d\n",i,j);
			} else if (s[i] == 10) {
				//fprintf(stderr,"matching begins\n");
				matching();
			}
			else {
				printf("wang yu zhong tian xia wu di, yang jing qin ye ye sheng hui.\n");
			}
		}
}

bool cmp(int i,int j)
{
	if (x[i]==x[j]) return y[i]<y[j];
	else return x[i]<x[j];
}

void change(int i,int j)
{
	nown[j]=max(nown[j]-nown[i],0);
	nowm[j]=max(nowm[j]-nown[i],0);
}

void die(int i)
{
	dead[i]=r[i];
}

long double combinational(int i)
{
	return fac[nown[i]]-fac[nowm[i]]-fac[nown[i]-nowm[i]];
}

bool cmp2(int i,int j)
{
	return sign(combinational(i)-combinational(j))<0;
}

void fight() {
	//fprintf(stderr,"fight begins\n");
	for (int i=1;i<=k;i++)
		id[i] = i;
	sort(id+1,id+k+1,cmp);
	for (int i=1;i<=k;)
	{
		int j=i;
		while (j<=k && x[id[j]]==x[id[i]] && y[id[j]]==y[id[i]])
			j++;
		bool exists[2] = {false,false};
		for (int t=i;t<j;t++)
			if (!dead[id[t]]) exists[c[id[t]]] = true;
		if (exists[0] && exists[1])
		{
			int cnt[2] = {0,0};
			for (int t=i;t<j;t++)
				if (!dead[id[t]])
				{
					cnt[c[id[t]]]++;
					q[c[id[t]]][cnt[c[id[t]]]]=id[t];
				}
			sort(q[0]+1,q[0]+cnt[0]+1,cmp2);
			sort(q[1]+1,q[1]+cnt[1]+1,cmp2);
			//fprintf(stderr,"One fight begins\n");
			//fprintf(stderr,"Team 0");
			//for (int t=1;t<=cnt[0];t++)
				//fprintf(stderr," %d",q[0][t]);
			//fprintf(stderr,"\n");
			//fprintf(stderr,"Team 1");
			//for (int t=1;t<=cnt[1];t++)
				//fprintf(stderr," %d",q[1][t]);
			//fprintf(stderr,"\n");
			int p1=cnt[0],p2=cnt[1];
			while (p1!=0 && p2!=0)
			{
				int id1=q[0][p1];
				int id2=q[1][p2];
				if (cmp2(id1,id2))
				{
					p1--;
					change(id1,id2);
					die(id1);
				}
				else
				{
					if (cmp2(id2,id1))
					{
						p2--;
						change(id2,id1);
						die(id2);
					}
					else
					{
						p1--;
						p2--;
						die(id2);
						die(id1);
					}
				}
			}
			//fprintf(stderr,"fight res %d %d\n",p1,p2);
		}
		i=j;
	}
}

void gg_check()
{
	for (int i=1;i<=k;i++)
		if (x[i]<1 || x[i]>n || y[i]<1 || y[i]>m)
		{
			printf("%d\n",h);
			exit(0);
		}
}

void simulate()
{
	for (int now_round=1;now_round<=R;now_round++)
	{
		//fprintf(stderr,"%d ronud begins\n",now_round);
		h = now_round;

		recover();
		log();
		move();
		skill();
		fight();
		//gg_check();
	}
	for (int i=1;i<=k;i++)
		printf("%d %d\n",x[i],y[i]);
}

int main()
{
	freopen("thupc2018_problem.in","r",stdin);
	freopen("thupc2018_problem.out","w",stdout);
	dx[0]=-1;dx[1]=1;dy[2]=-1;dy[3]=1;
	for (int a=1;a<=1000000;a++)
		fac[a]=fac[a-1]+logl(a);
	int T;
	scanf("%d",&T);
	for (int test=1;test<=T;test++)
	{
		//printf("%d\n",test);
		//fprintf(stderr,"%d game begins\n",test);
		init();
		simulate();
		//fprintf(stderr,"\n\n");
	}

	return 0;
}