社区讨论

AC但疑惑(数据过水?)

P2831[NOIP 2016 提高组] 愤怒的小鸟参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mi611jre
此快照首次捕获于
2025/11/19 21:17
3 个月前
此快照最后确认于
2025/11/21 00:00
3 个月前
查看原帖
(第零版没有EPS喜提WA 85pts)
以下是我的第一版代码:
CPP
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;

const ll INF = 1e18;
const double EPS = 1e-8;

pdd Computing_Function(pdd pig1, pdd pig2) {    //计算pig1和pig2和(0, 0)的二次函数系数
    double a = 
        (pig2.x*pig1.y - pig1.x*pig2.y) / ( (pig1.x*pig1.x)*pig2.x - pig1.x*(pig2.x*pig2.x) ), 
           b = 
        ((pig2.x*pig2.x)*pig1.y - (pig1.x*pig1.x)*pig2.y) / ( pig1.x*(pig2.x*pig2.x)-(pig1.x*pig1.x)*pig2.x );
    // cout << a << " " << b << "\n";
    return pdd{a, b};
}

bool Determine_Track(double a, double b, pdd pig) {    //判断pig是否在给定的抛物线上
    return fabs((a * pig.x * pig.x + b * pig.x) - pig.y) < EPS;
}

void solve() {
    ll n, m;
    cin >> n >> m;
    vector<pdd> pigs(n + 5);
    unordered_set<ll> track;     // 存储一个二进制表示这个二进制数所表示的两个小猪可以被一起消灭
    vector<ll> dp(300000, INF);    // dp[s]表示打掉小猪🐷的状态为s时最少需要的小鸟数量
    
    for(int i = 1; i <= n; i++) cin >> pigs[i].x >> pigs[i].y;
    for(int i = 1; i < n; i++) {
        for(int j = i + 1; j <= n; j++) {
            double a = Computing_Function(pigs[i], pigs[j]).first, b = Computing_Function(pigs[i], pigs[j]).second;
            if(a < 0) {
                ll index = ((1ll << (i - 1)) | (1ll << (j - 1)));
                for(int k = 1; k <= n; k++) {
                    if(k == i || k == j) continue;
                    if(Determine_Track(a, b, pigs[k])) index |= (1ll << (k - 1));
                }
                track.insert(index);
            }
        }
    }
        
    dp[0] = 0;

    for(ll s = 0; s <= (1 << n) - 1; s++) {
        for(auto x : track) {
            dp[s | x] = min(dp[s | x], dp[s] + 1);
        }
        for(int i = 1; i <= n; i++) {
            if(((1ll << (i - 1)) & s) == 0) {
                dp[s | (1ll << (i - 1))] = min(dp[s | (1ll << (i - 1))], dp[s] + 1);
            }
        }
    }

    cout << dp[(1 << n) - 1] << "\n";
}

int main() {
    ll t;
    cin >> t;
    while(t--) solve();
    return 0;
}
WA on #10
以下是我的第二版代码:
CPP
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;

const ll INF = 1e18;
const double EPS = 1e-8;

pdd Computing_Function(pdd pig1, pdd pig2) {    //计算pig1和pig2和(0, 0)的二次函数系数
    /*解方程
    {
    pig1.y = a * pig1.x * pig1.x + b * pig1.x, 
    pig2.y = a * pig2.x * pig2.x + b * pig2.x
    },
    容易得:*/

    // double a = 
    //     (pig2.x*pig1.y - pig1.x*pig2.y) / ( (pig1.x*pig1.x)*pig2.x - pig1.x*(pig2.x*pig2.x) ), 
    //        b = 
    //     ((pig2.x*pig2.x)*pig1.y - (pig1.x*pig1.x)*pig2.y) / ( pig1.x*(pig2.x*pig2.x)-(pig1.x*pig1.x)*pig2.x );
    // 弃用,可能存在其他情况未处理
    
    double x1 = pig1.x, y1 = pig1.y;
    double x2 = pig2.x, y2 = pig2.y;
    
    if(fabs(x1) < EPS || fabs(x2) < EPS) return pdd{0, 0};

    if(fabs(x1 - x2) < EPS) return pdd{0, 0};

    double ad = ( (x1*x1)*x2 - x1*(x2*x2) ), bd = ( x1*(x2*x2)-(x1*x1)*x2 );

    if(fabs(ad) < EPS) return pdd{0, 0};
    if(fabs(bd) < EPS) return pdd{0, 0};
    
    double a = (x2*y1 - x1*y2) / ad, b = ((x2*x2)*y1 - (x1*x1)*y2) / bd;
    
    return pdd{a, b};
}

bool Determine_Track(double a, double b, pdd pig) {    //判断pig是否在给定的抛物线上
    return fabs((a * pig.x * pig.x + b * pig.x) - pig.y) < EPS;
}

void solve() {
    ll n, m;
    cin >> n >> m;
    vector<pdd> pigs(n + 5);
    unordered_set<ll> track;     // 存储一个二进制表示这个二进制数所表示的两个小猪可以被一起消灭
    vector<ll> dp(300000, INF);    // dp[s]表示打掉小猪🐷的状态为s时最少需要的小鸟数量
    
    for(int i = 1; i <= n; i++) cin >> pigs[i].x >> pigs[i].y;
    for(int i = 1; i < n; i++) {
        for(int j = i + 1; j <= n; j++) {
            pdd x = Computing_Function(pigs[i], pigs[j]);
            double a = x.first, b = x.second;
            if(a == 0 && b == 0) continue;
            if(a < EPS) {
                ll index = ((1ll << (i - 1)) | (1ll << (j - 1)));
                for(int k = 1; k <= n; k++) {
                    if(k == i || k == j) continue;
                    if(Determine_Track(a, b, pigs[k])) index |= (1ll << (k - 1));
                }
                track.insert(index);
            }
        }
    }

    dp[0] = 0;

    for(ll s = 0; s <= (1 << n) - 1; s++) {
        for(auto x : track) {
            dp[s | x] = min(dp[s | x], dp[s] + 1);
        }
        for(int i = 1; i <= n; i++) {
            if(((1ll << (i - 1)) & s) == 0) {
                dp[s | (1ll << (i - 1))] = min(dp[s | (1ll << (i - 1))], dp[s] + 1);
            }
        }
    }

    cout << dp[(1 << n) - 1] << "\n";
}

int main() {
    ll t;
    cin >> t;
    while(t--) solve();
    return 0;
}
AC但是样例二多测三本地与lg上跑的结果不一样 本地是对的 lg上样例二多测三输出3
求神犇解析

回复

1 条回复,欢迎继续交流。

正在加载回复...