洛谷 P2831 [NOIP2016]愤怒的小鸟

传送

一些废话

题太难了,于是这次不写解析,具体思路可以看这位聚聚的博客:

聚聚的博客

这里说对搜索题的一点看法。

首先是实数域上的搜索。对于本题而言,显然抛物线的每个参数都是实数,断绝了一般枚举的可能。对于这类情况,常用的转化是:

枚举所有的情况 -> 枚举可能的情况

对于本题,具体而言,显然绝大部分抛物线都是无用的,而两只猪的坐标可以确定一条过原点的抛物线(当然,别忘了排除不合法的情况),所以我们枚举所有这样的猪对即可。

与本题类似地,有 \(uva303\) ,如果有兴趣可以去看一眼。

其次,每条抛物线可能击杀多只猪,但每次都去判断是否击杀某只猪过于奢侈,于是我们对每条抛物线就算一次,把能击杀的猪用二进制数存起来。这也是一个常用的优化策略避免赘余运算

以上。

参考程序

#include<iostream>
#include<vector>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,t,bin[20][20],mem[1<<18];
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
struct pig{
    double x,y;
}p[20];
inline double calca(pig i,pig j){
    return (j.x * i.y - i.x * j.y)
     / (i.x * j.x * (i.x - j.x));
}
inline double calcb(pig i,pig j){
    return (i.x * i.x * j.y - j.x * j.x * i.y)
     / (i.x * j.x * (i.x - j.x));
}
void calc(double a,double b){
    vector<int> kill;
    int state = 0;
    for(int i = 0;i < n;i++)
        if(fabs(a * p[i].x * p[i].x + b * p[i].x - p[i].y) < eps){
            state |= (1<<i);
            kill.push_back(i);
        }
    for(int i = 0;i < kill.size();i++)
        for(int j = i + 1;j < kill.size();j++)
            bin[kill[i]][kill[j]] = bin[kill[j]][kill[i]] = state;
}
int dfs(int state){
    if(mem[state] != -1) return mem[state];
    mem[state] = inf;
    for(int i = 0;i < n;i++){
        if(state & (1<<i)) continue;
        bool flag = 0;
        for(int j = 0;j < n;j++)
            if((state & (1<<j)) == 0 && p[i].x != p[j].x && calca(p[i],p[j]) < 0.0){
                flag = 1;
                if(bin[i][j] == -1) calc(calca(p[i],p[j]),calcb(p[i],p[j]));
                mem[state] = min(mem[state],dfs(state | bin[i][j]) + 1);
            }
        if(!flag) return mem[state] = dfs(state | (1<<i)) + 1;
    }
    return mem[state];
    
}
int main(){
    cin >> t;
    while(t--){
        cin >> n >> m;
        for(int i = 0;i < n;i++)
            cin >> p[i].x >> p[i].y;
        memset(bin,-1,sizeof(bin));
        memset(mem,-1,sizeof(mem));
        mem[(1<<n)-1] = 0;
        cout << dfs(0) << endl;
    }
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/mysterious-garden/p/9884994.html
今日推荐