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
21 1 1 -1
-1 -1 -1 1
2
1 1 -1 -1
1 -1 -1 1
Sample Output
1.411.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
33 1
3 2
4 2
Sample Output
0.33330.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 101 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; }
相关文章推荐
- c++之模板
- Mifare系列7-安全性(转)
- linux或mac系统下的端口转发
- Servlet的异常处理机制
- UVa 12275 Sensor network 生成树
- 高效程序员的狂暴之路
- Java 创建对象有哪几种方式
- SQLite Android数据库详解
- Mifare系列6-射频卡与读写器的通信(转)
- 搭建go开发环境时,出现GoSublime error: MarGo build failed的问题
- 黑马程序员--动态类型检测
- 【五校联考2015 9.5】送你一棵线段树
- Android 之数据存储--SharedPreferences
- Android数据存储
- 英文语句处理(空格处理)
- 关于synchronized关键字的一点补充
- win7配置sql server 2005数据库服务器
- 面试之简答题
- 赋值运算符的重载
- android 动画 从view顶部退出、进入(系列动画)