(纪中)3539. Reflect Damage【高斯消元】【数论】

这篇博客探讨了一种利用高斯消元法解决复杂反射伤害计算的问题。文章首先介绍了问题背景,即每对个体间的伤害可以无限次反射,伤害计算涉及到每个个体受到的初始伤害和反射伤害。接着,博主详细阐述了如何设置方程组,并运用高斯消元模板求解每个个体最终受到的伤害。代码示例展示了C++实现这一算法的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
在这里插入图片描述


解题思路

题意:每对折射关系,可以无限次折射给其他人,只要当前这个人受到伤害。

设a[i]表示i受到的初始伤害,f[i]表示i受到的总伤害(初始伤害+被别人折射过来的伤害,不减去自己折射出去的),p[i]表示i折射出去的比例和。则显然,i最终受到的伤害为f[i]*(1-p[i]):

p[i]p[i]p[i]可以在读入的时候直接处理出来,所以现在要求的是f[i]f[i]f[i]。我们设c[i][j]c[i][j]c[i][j]表示iiijjj的伤害率,则:

  • f[i]=a[i]+f[i]=a[i]+f[i]=a[i]+∑j!=if[j]∗c[j][i]\sum_{j!=i}f[j]*c[j][i]j!=if[j]c[j][i]

a[i],c[j][i]都已知,f[i]是未知数,则把式子移项得:

  • ∑j!=if[j]∗c[j][i]−f[i]=−a[i]\sum_{j!=i}f[j]*c[j][i]-f[i]=-a[i]j!=if[j]c[j][i]f[i]=a[i]

这样的式子有n个,每个式子的未知数都是n个,且都是我们要求的,所以解出所有的方程就行了——高斯消元模板。

(其中f[i]f[i]f[i]的系数为−1-11,注意a[i]a[i]a[i]符号应该是负的,但是初值给的是正的所以最后要取absabsabs


代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;

int n,m,x,y;
double a[210],c[210][210],p[210],z;

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lf",&a[i]);
		c[i][n+1]=a[i];
	}	
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%lf",&x,&y,&z);
		c[y][x]+=z;
		p[x]+=z;
	}
	for(int i=1;i<=n;i++)
		c[i][i]=-1;
	for(int i=1;i<=n;i++)
	{
		int maxn=i;
		for(int j=i+1;j<=n;j++)
		{
			if(abs(c[j][i])>abs(c[maxn][i]))
				maxn=j;
		}
		for(int j=1;j<=n+1;j++)
			swap(c[i][j],c[maxn][j]);
		for(int j=1;j<=n;j++)
		{
			if(i!=j)
			{
				double tmp=c[j][i]/c[i][i];
				for(int t=1;t<=n+1;t++)
					c[j][t]-=c[i][t]*tmp;
			}
		}
	}
	for(int i=1;i<=n;i++)
		printf("%.6lf\n",abs(c[i][n+1]/c[i][i]*(1-p[i])));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值