1. 程式人生 > 其它 >【題解】AcWing 1390.通電圍欄

【題解】AcWing 1390.通電圍欄

題目傳送門

題目描述

農夫約翰的牧場可以看作是一個二維平面。

約翰為了方便看管他養的牛,構建了一個三角形的通電圍欄。

他希望他的奶牛都在圍欄圍起的區域內活動。

三角形圍欄的三個頂點位置座標分別為 (0,0),(n,m),(p,0),該圍欄由三個頂點兩兩相連而成。

平面上,所有位於三角形圍欄內部(不包括邊)且橫縱座標都為整數的點上都可以放置一頭奶牛。

請問,圍欄中最多可以放置多少頭奶牛。

輸入格式

共一行,包含三個整數 n,m,p。

輸出格式

輸出一個整數,表示可放置的牛的最大數量。

資料範圍

0≤n<32000,
0<m<32000,
0<p<32000

輸入樣例:

7 5 10

輸出樣例:

20

演算法1

(暴力?模擬) \(O(n)\)

就是把每個x的三角形三條線所對的y值算出,然後想想自己怎麼做的,就是統計y1到y2點有幾個,
這邊也沒有特別的暴力,比較完全暴力是\(O(n^2)\)時間會超,所以運用簡單的數學知識中的斜率來做就好。

這裡需要注意的主要是n與p的關係
n < p 的時候下面的線是k = 0 的線
n > p 的時候是要求的兩條線之間的點,就要相減了

還有兩點注意點

  1. 當這個點算出剛好是整點的情況
  2. double的精度誤差

C++ 程式碼

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

typedef long long LL;

int n, m, p;
double k1, k2, b2;

inline int get_cnt(double x)
{
    if(p > n)
    {
        if(x < n) return (int)(k1 * x - 1e-8);
        return (int)(k2 * x + b2 - 1e-8);
    }
    if(x < p) return (int)(k1 * x - 1e-8);
    return (int)(k1 * x - 1e-8) - (int)(k2 * x + b2 + 1e-8); // l2: (- 1e-8) x
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m >> p;
	k1 = 1.0 * m / n, k2 = 1.0 * m / (n - p), b2 = - k2 * p;
// 	cout << k1 << ' ' << k2 << ' ' << b2 << endl;
	LL res = 0;
	for(int i = 1; i < max(p, n); i ++)
	{
	    res += get_cnt(i);
	   // cout << get_cnt(i) << endl;
	}
	cout << res << endl;
	return 0;
}