您的位置:首页 > 其它

2010 Asia Regional Tianjin Site —— Online Contest (线段树二维转一维,2-SAT,floyed变形)hdu3621-3631

2015-09-07 21:50 281 查看

Bomb Game

Problem Description

Robbie is playing an interesting computer game. The game field is an unbounded 2-dimensional region. There are N rounds in the game. At each round, the computer will give Robbie two places, and Robbie should choose one of them to put a bomb. The explosion area of the bomb is a circle whose center is just the chosen place. Robbie can control the power of the bomb, that is, he can control the radius of each circle. A strange requirement is that there should be no common area for any two circles. The final score is the minimum radius of all the N circles.

Robbie has cracked the game, and he has known all the candidate places of each round before the game starts. Now he wants to know the maximum score he can get with the optimal strategy.

Input

The first line of each test case is an integer N (2 <= N <= 100), indicating the number of rounds. Then N lines follow. The i-th line contains four integers x1i, y1i, x2i, y2i, indicating that the coordinates of the two candidate places of the i-th round are (x1i, y1i) and (x2i, y2i). All the coordinates are in the range [-10000, 10000].

Output

Output one float number for each test case, indicating the best possible score. The result should be rounded to two decimal places.

Sample Input

2

1 1 1 -1

-1 -1 -1 1

2

1 1 -1 -1

1 -1 -1 1

Sample Output

1.41

1.00

思路:对于这2*N个点,如果两个点之间“矛盾”,对于本题即两个圆相交,则连一条边。对这个图求强连通分量,然后看是否有某对点属于同一个强连通分量。如果N对点每一对都属于不同的强连通分量,满足。否则不满足。然后二分半径即可。

[code]#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=210;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
const double EPS=1e-3;
int n;  
struct Edge{  
    int v,next;  
    Edge(){}  
    Edge(int _v,int _next):v(_v),next(_next){}  
}edge[MAXN*MAXN];  
int head[MAXN], size;  
inline void initial(){  
    memset(head,-1,sizeof(int)*(n+2));  
    size = 0;  
}  
inline void add_edge(int u,int v){  
    edge[size] = Edge(v,head[u]);  
    head[u] = size ++;  
}  
int belong[MAXN];   
bool vis[MAXN];  
int depth;                   
int bcnt;                    
int dfn[MAXN], low[MAXN];    

int stack[MAXN], tail ;  
inline void Tarjan(int u){  
    dfn[u] = low[u] = depth ++;  
    vis[u] = 1;  
    stack[++tail] = u;  
    for(int i = head[u];i != -1;i = edge[i].next){  
        int v = edge[i].v;  
        if(dfn[v] == -1){  
            Tarjan(v);  
            if(low[u] > low[v])  
                low[u] = low[v];  
        }else if(vis[v] && low[u] > dfn[v]){  
                low[u] = dfn[v];  
        }  
    }  
    if(low[u] == dfn[u]){    
        bcnt ++;  
        int j;  
        do{  
            j = stack[tail--];  
            vis[j] = 0;  
            belong[j] = bcnt;  
        }while(j != u);  
    }  
}  
double x[MAXN], y[MAXN];  
inline double Cal(int i,int j){  
    return (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]);  
}  
inline bool can(){  
    int N = n/2;  
    for(int i = 1;i <= N; ++i)  
        if(belong[i] == belong[i+N]) return false;  
    return true;  
}  
int main(){  
    int N;  
    while(scanf("%d",&N) != EOF){  
        n = 2*N;  
        for(int i = 1;i <= N; ++i)  
            scanf("%lf%lf%lf%lf",&x[i],&y[i],&x[i+N],&y[i+N]);  
        double right = 10000.0*10000.0, left = 0.0, mid;  
        while(right - left >= EPS){  
            mid = (right + left)/2.0;  
            initial();  
            for(int i = 1;i < n; ++i)  
                for(int j = i + 1;j <= n; ++j){  
                    if(Cal(i,j) < mid){  
                        int u, v;  
                        if(i <= N) u = i + N;  
                        else u = i - N;  
                        if(j <= N) v = j + N;  
                        else v = j - N;  
                        add_edge(i,v);  
                        add_edge(j,u);  
                    }  
                }  
            tail = depth = bcnt = 0;  
            memset(vis,0,sizeof(bool)*(n+2));  
            memset(dfn,-1,sizeof(int)*(n+2));  
            memset(low,0,sizeof(int)*(n+2));  
            for(int i = 1;i <= n; ++i)  
                if(dfn[i] == -1) Tarjan(i);  
            if(can()) left = mid;  
            else right = mid;  
        }  
        printf("%.2lf\n",sqrt(left)/2.0);  
    }  
}


Examining the Rooms

Problem Description

A murder happened in the hotel. As the best detective in the town, you should examine all the N rooms of the hotel immediately. However, all the doors of the rooms are locked, and the keys are just locked in the rooms, what a trap! You know that there is exactly one key in each room, and all the possible distributions are of equal possibility. For example, if N = 3, there are 6 possible distributions, the possibility of each is 1/6. For convenience, we number the rooms from 1 to N, and the key for Room 1 is numbered Key 1, the key for Room 2 is Key 2, etc.

To examine all the rooms, you have to destroy some doors by force. But you don’t want to destroy too many, so you take the following strategy: At first, you have no keys in hand, so you randomly destroy a locked door, get into the room, examine it and fetch the key in it. Then maybe you can open another room with the new key, examine it and get the second key. Repeat this until you can’t open any new rooms. If there are still rooms un-examined, you have to randomly pick another unopened door to destroy by force, then repeat the procedure above, until all the rooms are examined.

Now you are only allowed to destroy at most K doors by force. What’s more, there lives a Very Important Person in Room 1. You are not allowed to destroy the doors of Room 1, that is, the only way to examine Room 1 is opening it with the corresponding key. You want to know what is the possibility of that you can examine all the rooms finally.

Input

The first line of the input contains an integer T (T ≤ 200), indicating the number of test cases. Then T cases follow. Each case contains a line with two numbers N and K. (1 < N ≤ 20, 1 ≤ K < N)

Output

Output one line for each case, indicating the corresponding possibility. Four digits after decimal point are preserved by rounding.

Sample Input

3

3 1

3 2

4 2

Sample Output

0.3333

0.6667

0.6250

Hint

Sample Explanation

When N = 3, there are 6 possible distributions of keys:

[code]Room 1  Room 2  Room 3  Destroy Times


1 Key 1 Key 2 Key 3 Impossible #2 Key 1 Key 3 Key 2 Impossible #3 Key 2 Key 1 Key 3 Two #4 Key 3 Key 2 Key 1 Two #5 Key 2 Key 3 Key 1 One #6 Key 3 Key 1 Key 2 One

In the first two distributions, because Key 1 is locked in Room 1 itself and you can’t destroy Room 1, it is impossible to open Room 1.

In the third and forth distributions, you have to destroy Room 2 and 3 both. In the last two distributions, you only need to destroy one of Room 2 or Room

[code]#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;

const int MAXN=25;
const int MAXM=15;
const LL INF=0x3f3f3f3f;

int T,N,K;
LL dp[MAXN][MAXN];

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&K);
        LL fac=1;
        for(int i=2;i<=N;i++) fac*=i;
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(int i=1;i<=N;i++)
            for(int j=1;j<=i;j++){
                dp[i][j]=dp[i-1][j]*(i-1)+dp[i-1][j-1];
            }
        LL ans=0,ans2=0;
        for(int i=1;i<=K;i++) ans+=dp
[i];
        for(int i=1;i<=K-1;i++) ans2+=dp[N-1][i];
        printf("%.4f\n",(double)(ans-ans2)/fac);
    }
    return 0;
}


Shortest Path

Problem Description

When YY was a boy and LMY was a girl, they trained for NOI (National Olympiad in Informatics) in GD team. One day, GD team’s coach, Prof. GUO asked them to solve the following shortest-path problem.

There is a weighted directed multigraph G. And there are following two operations for the weighted directed multigraph:

(1) Mark a vertex in the graph.

(2) Find the shortest-path between two vertices only through marked vertices.

For it was the first time that LMY faced such a problem, she was very nervous. At this moment, YY decided to help LMY to analyze the shortest-path problem. With the help of YY, LMY solved the problem at once, admiring YY very much. Since then, when LMY meets problems, she always calls YY to analyze the problems for her. Of course, YY is very glad to help LMY. Finally, it is known to us all, YY and LMY become programming lovers.

Could you also solve the shortest-path problem?

Input

The input consists of multiple test cases. For each test case, the first line contains three integers N, M and Q, where N is the number of vertices in the given graph, N≤300; M is the number of arcs, M≤100000; and Q is the number of operations, Q ≤100000. All vertices are number as 0, 1, 2, … , N - 1, respectively. Initially all vertices are unmarked. Each of the next M lines describes an arc by three integers (x, y, c): initial vertex (x), terminal vertex (y), and the weight of the arc (c). (c > 0) Then each of the next Q lines describes an operation, where operation “0 x” represents that vertex x is marked, and operation “1 x y” finds the length of shortest-path between x and y only through marked vertices. There is a blank line between two consecutive test cases.

End of input is indicated by a line containing N = M = Q = 0.

Output

Start each test case with “Case #:” on a single line, where # is the case number starting from 1.

For operation “0 x”, if vertex x has been marked, output “ERROR! At point x”.

For operation “1 x y”, if vertex x or vertex y isn’t marked, output “ERROR! At path x to y”; if y isn’t reachable from x through marked vertices, output “No such path”; otherwise output the length of the shortest-path. The format is showed as sample output.

There is a blank line between two consecutive test cases.

Sample Input

5 10 10

1 2 6335

0 4 5725

3 3 6963

4 0 8146

1 2 9962

1 0 1943

2 1 2392

4 2 154

2 2 7422

1 3 9896

0 1

0 3

0 2

0 4

0 4

0 1

1 3 3

1 1 1

0 3

0 4

0 0 0

Sample Output

Case 1:

ERROR! At point 4

ERROR! At point 1

0

0

ERROR! At point 3

ERROR! At point 4

floyed变形

[code]#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=310;
const int maxm=1010;
const int MOD=1e9+7;
const LL INF=1e18;
int N,M,Q;
LL f[maxn][maxn];
int vis[maxn];
LL dis[maxn][maxn];
int main(){
    int u,v,x,op;
    int cas=1;
    bool first=true;
    while(scanf("%d%d%d",&N,&M,&Q)!=EOF,N+M+Q){
        if(first)first=false;
        else printf("\n");
        memset(vis,0,sizeof(vis));
        memset(dis,-1,sizeof(dis));
        for(int i=0;i<=N;i++){
            for(int j=0;j<=N;j++){
                f[i][j]=INF;
            }
        }
        for(int i=0;i<M;i++){
            scanf("%d%d%d",&u,&v,&x);
            if(dis[u][v]==-1)dis[u][v]=x;
            else dis[u][v]=min(dis[u][v],1LL*x);
        }
        for(int i=0;i<=N;i++)dis[i][i]=0,f[i][i]=0;
        printf("Case %d:\n",cas++);
        while(Q--){
            scanf("%d",&op);
            if(op==0){
                scanf("%d",&u);
                if(vis[u])printf("ERROR! At point %d\n",u);
                else {
                    vis[u]=1;
                    for(int i=0;i<N;i++){
                        if(dis[i][u]==-1)continue;
                        for(int j=0;j<N;j++){
                            if(f[j][i]==INF)continue;
                            f[j][u]=min(f[j][u],f[j][i]+dis[i][u]);
                        }
                    }
                    for(int i=0;i<N;i++){
                        if(f[i][u]==INF)continue;
                        for(int j=0;j<N;j++){
                            if(f[u][j]==INF)continue;
                            f[i][j]=min(f[i][j],f[i][u]+f[u][j]);
                        }
                    }
                }
            } else {
                scanf("%d%d",&u,&v);
                if(!vis[u]||!vis[v]){
                    printf("ERROR! At path %d to %d\n",u,v);
                } else if(f[u][v]==INF){
                    printf("No such path\n");
                } else{
                    printf("%I64d\n",f[u][v]);
                }
            }
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: