(第12回ブルーブリッジカップ州大会)テスト問題C直線(セット+精度低下防止)

トピック:

この問題は、kとbを直接激しく解き、kとbを2つのタプルとしてセットに入れ、最後にセット内の要素の数を直接記録することができますが、注意すべき点の1つは、浮動小数点を使用することです。演算の精度が低下するため、精度が低下した後の数値を使用して計算することは避けてください。つまり、bを解くときに、kを使用して計算に組み込むことはできません。 kを計算するプロセスなので、kの計算式置換法を使用してbを計算する必要があります

y1 = k * x1+bおよびy2=k * x2+bの場合

最初にkを計算したので、 k =(y1-b)/ x1、b = y2-k * x2であることがわかりますが、この時点でkの精度が低下しているため、以前に計算したkを使用しないでください。もう一度次の式に代入してbを計算しますが、次の式に(y1-b)/ x1を使用してbを計算する必要があります。つまり、この式を使用してb =(x1y2-y1x2)/(x1-x2)を計算します。精度の低下を抑えてbを計算することが可能です

特殊なケースを防ぐために、勾配が0で、勾配が個別に存在しない場合を検討することをお勧めします。これは、xの間隔の長さが変化する+yの間隔の長さが変化するということを考慮してください。 、いくつかのエラーを効果的に回避できる、以下はコードです:
 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
typedef pair<double,double>PII;
int main()
{
	set<PII>p;
	for(int i=0;i<20;i++)
	for(int j=0;j<21;j++)
	for(int k=0;k<20;k++)
	for(int l=0;l<21;l++)
	{
		if(i==k||j==l) continue;
		double kk=1.0*(l-j)/(k-i);
		double b=1.0*(i*l-j*k)/(i-k);
		p.insert({kk,b});
	}
	cout<<p.size()+41;
	return 0;
}

結果は40257です

おすすめ

転載: blog.csdn.net/AC__dream/article/details/123958806