hdu 4305 Lightning 高斯消元 计算几何

Lightning

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1432    Accepted Submission(s): 455


Problem Description
There are N robots standing on the ground (Don't know why. Don't know how).

Suddenly the sky turns into gray, and lightning storm comes! Unfortunately, one of the robots is stuck by the lightning!

So it becomes overladen. Once a robot becomes overladen, it will spread lightning to the near one.


The spreading happens when:
  Robot A is overladen but robot B not.
  The Distance between robot A and robot B is no longer than R.
  No other robots stand in a line between them.
In this condition, robot B becomes overladen.

We assume that no two spreading happens at a same time and no two robots stand at a same position.


The problem is: How many kind of lightning shape if all robots is overladen? The answer can be very large so we output the answer modulo 10007. If some of the robots cannot be overladen, just output -1.
 

Input
There are several cases.
The first line is an integer T (T < = 20), indicate the test cases.
For each case, the first line contains integer N ( 1 < = N < = 300 ) and R ( 0 < = R < = 20000 ), indicate there stand N robots; following N lines, each contains two integers ( x, y ) ( -10000 < = x, y < = 10000 ), indicate the position of the robot.
 

Output
One line for each case contains the answer.
 

Sample Input
      
      
3 3 2 -1 0 0 1 1 0 3 2 -1 0 0 0 1 0 3 1 -1 0 0 1 1 0
 

Sample Output
      
      
3 1 -1



这道题题意:


有很多机器人,机器人可能被闪电打中,被电到的机器人可以传导电到半径为R的其他机器人上,但是要求两个机器人之间不能有其他机器人

每次传递,只能由其中一个机器人传递给另一个,任意机器人可以作为起点。

问所有机器人被电到能形成几种图形,

有些机器人不能电到输出-1



解题:

1. 用计算几何处理,把相互可达的点记录下来用假设Dist[i][j]=1 表示i,j可达

  dist[i][j] = 0表示i,j不可达,i=j,dist[i][j]=0;


 2. 有个生成树计数算法。百度一下,

    意思是A[i][j] i!=j A[i][j] =0;

    i==j    A[i][i]表示与i相连的边数

   另D = A-Dist

则D的任意一个n-1阶的行列式就是答案。

高斯消元算行列式


3. 数字可能很大要取模

要计算逆元   求a关于p的逆元

      另ax+py=1

x就是a的逆元


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
#define ll long long
#define maxn 307
#define mod 10007
struct Point{
    int x,y;
    Point (int x=0,int y=0):x(x),y(y){}
};
int Length(Point a){
    return a.x*a.x+a.y*a.y;
}
Point operator-(Point a,Point b){
    return Point(a.x-b.x,a.y-b.y);
}
int Cross(Point a,Point b){
    return a.x*b.y-a.y*b.x;
}

int Dot(Point a,Point b){
    return a.x*b.x+a.y*b.y;
}
int Onsegment(Point a,Point b,Point c){
    if(Cross(a-c,b-c) != 0) return 0;
    if(Dot(a-b,a-c) < 0) return 1;
    return 0;
}
Point point[maxn];
int dist[maxn][maxn];

void getDist(int n,int r){
    memset(dist,0,sizeof(dist));
    int flag ;
    for(int i = 0;i < n; i++){
        for(int j = i+1;j < n;j++){
            if(Length(point[i]-point[j]) <= r*r){
                flag = 0;
                for(int k = 0;k < n; k++){
                    if(k == i || k == j) continue;
                    if(Onsegment(point[k],point[i],point[j])){
                        flag = 1; break;
                    }
                }
                if(flag == 0) dist[i][j] = dist[j][i] = 1;
            }
        }
    }
}

int inv[mod+10];

void gcd(int a,int b,int &x,int &y){
    if(b == 0 ){
        x = 1;
        y = 0;
        return ;
    }
    gcd(b,a%b,x,y);
    int y1 = y;
    y = x-a/b*y;
    x = y1;
}

int check[maxn];
int dfs(int u){
    if(check[u]) return 0;
    check[u] = 1;
    int ans = 1;
    for(int i = 0;i < maxn; i++)
        if(dist[u][i] == 1)
         ans+=dfs(i);
    return ans;
}
struct Matrix{
    int matrix[maxn][maxn];
    void init(){
        memset(matrix,0,sizeof(matrix));
    }
    int Det(int n,  int mod1){
        int ans = 1;

         for(int i = 0;i < n;i++)
            for(int j = 0;j < n;j++)
                matrix[i][j] = (matrix[i][j]+mod1)%mod1;


        for(int i = 0;i < n; i++){
            int p=i,x=matrix[i][i];
            //寻找列主元
            for(int j = i+1;j < n; j++){
                if(abs(matrix[j][i]) > abs(x)){
                    x = matrix[j][i];
                    p = j;
                }
            }
            for(int j = i;j < n; j++)
                swap(matrix[p][j],matrix[i][j]);

            if(p != i) ans = -ans;
            if(ans < 0) ans+=mod1;
            if(matrix[i][i] == 0) return -1;
            ans = ans*matrix[i][i]%mod1;
            matrix[i][i] %= mod1;
            if(matrix[i][i] < 0) matrix[i][i]+=mod1;
            matrix[i][i] = inv[matrix[i][i]];
            for(int j = i+1;j < n; j++){
                if(matrix[j][i] == 0) continue;
                matrix[j][i] = (matrix[j][i]*matrix[i][i])%mod1;
                for(int k = i+1;k<n;k++){
                    matrix[j][k] = (matrix[j][k]-matrix[i][k]*matrix[j][i])%mod1;
                    if(matrix[j][k] < 0) matrix[j][k]+=mod1;
                }
            }

        }
        return (ans%mod1+mod1)%mod1;
    }
};

int main(){
    int n,t,r,x,y;
    Matrix mat;
    for(int i = 1;i < mod;i++){
        gcd(i,mod,x,y);
        inv[i] = (x%mod+mod)%mod;
    }

    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&r);
        for(int i = 0;i < n; i++)
            scanf("%d%d",&point[i].x,&point[i].y);
        getDist(n,r);

        memset(check,0,sizeof(check));
        if(dfs(0) != n){
            printf("-1\n");
            continue;
        }

        mat.init();
        for(int i = 0;i < n; i++)
            for(int j = 0;j < n; j++){
                if(dist[i][j] == 1){
                    mat.matrix[i][j] = -1;
                    mat.matrix[i][i]++;
                }
            }
        int ans = mat.Det(n-1,mod);

        printf("%d\n",ans);
    }
    return 0;
}
























  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值