【纪中受难记】——C3D6:大小不分

四道b组水题,由于空间开错而痛失成绩


 

 

Description

Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农场)。有些农场之间原本就有道路相连。所有N(1 <= N <= 1,000)个农场(用1..N顺次编号)在地图上都表示为坐标为(X_i, Y_i)的点(0 <= X_i <= 1,000,000;0 <= Y_i <= 1,000,000),两个农场间道路的长度自然就是代表它们的点之间的距离。现在Farmer John也告诉了你农场间原有的M(1 <= M <= 1,000)条路分别连接了哪两个农场,他希望你计算一下,为了使得所有农场连通,他所需建造道路的最小总长是多少。
 

Input

* 第1行: 2个用空格隔开的整数:N 和 M
* 第2..N+1行: 第i+1行为2个用空格隔开的整数:X_i、Y_i
* 第N+2..N+M+2行: 每行用2个以空格隔开的整数i、j描述了一条已有的道路,这条道路连接了农场i和农场j

Output

* 第1行: 输出使所有农场连通所需建设道路的最小总长,保留2位小数,不必做 任何额外的取整操作。为了避免精度误差,计算农场间距离及答案时请使用64位实型变量
 

Sample Input

4 1
1 1
3 1
2 3
4 3
1 4

Sample Output

4.00
 

Data Constraint

 
 

Hint

样例说明:
FJ选择在农场1和农场2间建一条长度为2.00的道路,在农场3和农场4间建一条长度为2.00的道路。这样,所建道路的总长为4.00,并且这是所有方案中道路总长最小的一种。

 

没啥好讲的,最小生成树板子。注意取根号要先long long

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 int n,m;
17 const int N=1010;
18 struct node{
19     int x,y;
20     double dis;
21     bool operator < (const node &x) const{
22         return dis<x.dis;
23     }
24 }h[N*N+N];
25 long long X[N],Y[N];
26 double getdis(int x,int y){
27     long long tmp=(X[x]-X[y])*(X[x]-X[y])+(Y[x]-Y[y])*(Y[x]-Y[y]);
28     return sqrt(tmp);
29 }
30 int f[N];
31 int find(int x){
32     return x==f[x]?x:f[x]=find(f[x]);
33 }
34 int vis[N][N];
35 int main(){
36     n=read();
37     m=read();
38     for(int i=1;i<=n;i++){
39         f[i]=i;
40         X[i]=read();
41         Y[i]=read();
42     }
43     for(int i=1;i<=m;i++){
44         h[i].x=read();
45         h[i].y=read();
46         h[i].dis=0;
47         vis[h[i].x][h[i].y]=1;
48     }
49     int cnt=m;
50     for(int i=1;i<=n;i++){
51         for(int j=1;j<i;j++){
52             if(!vis[i][j]){
53                 h[++cnt].x=i;h[cnt].y=j;
54                 h[cnt].dis=getdis(i,j);
55                 vis[i][j]=1;
56             }
57         }
58     }
59     sort(h+1,h+cnt+1);
60     double ans=0;
61     for(int i=1;i<=cnt;i++){
62         int fax=find(h[i].x),fay=find(h[i].y);
63         if(fax!=fay){
64             ans+=h[i].dis;
65             f[fax]=fay;
66         }
67     }
68     
69     printf("%.2lf",ans);
70     return 0;
71 }

Description

清早6:00,Farmer John就离开了他的屋子,开始了他的例行工作:为贝茜挤奶。前一天晚上,整个农场刚经受过一场瓢泼大雨的洗礼,于是不难想见,FJ现在面对的是一大片泥泞的土地。FJ的屋子在平面坐标(0, 0)的位置,贝茜所在的牛棚则位于坐标(X,Y) (-500 <= X <= 500; -500 <= Y <= 500)处。当然咯,FJ也看到了地上的所有N(1 <= N <= 10,000)个泥塘,第i个泥塘的坐标为(A_i, B_i) (-500 <= A_i <= 500;-500 <= B_i <= 500)。每个泥塘都只占据了它所在的那个格子。
Farmer John自然不愿意弄脏他新买的靴子,但他同时想尽快到达贝茜所在的位置。为了数那些讨厌的泥塘,他已经耽搁了一些时间了。如果Farmer John只能平行于坐标轴移动,并且只在x、y均为整数的坐标处转弯,那么他从屋子门口出发,最少要走多少路才能到贝茜所在的牛棚呢?你可以认为从FJ的屋子到牛棚总是存在至少一条不经过任何泥塘的路径。
 

Input

* 第1行: 3个用空格隔开的整数:X,Y 和 N
* 第2..N+1行: 第i+1行为2个用空格隔开的整数:A_i 和 B_i

Output

* 第1行: 输出1个整数,即FJ在不踏进泥塘的情况下,到达贝茜所在牛棚所需要走过的最小距离
 

Sample Input

1 2 7
0 2
-1 3
3 1
1 1
4 2
-1 1
2 2

Sample Output

11
 

Data Constraint

 
 

Hint

样例解释:
贝茜所在牛棚的坐标为(1, 2)。Farmer John能看到7个泥塘,它们的坐标分
别为(0, 2)、(-1, 3)、(3, 1)、(1, 1)、(4, 2)、(-1, 1)以及(2, 2)。
以下为农场的简图:(*为FJ的屋子,B为贝茜呆的牛棚)
4 . . . . . . . . 
3 . M . . . . . . 
Y 2 . . M B M . M . 
1 . M . M . M . . 
0 . . * . . . . . 
-1 . . . . . . . . 
-2-1 0 1 2 3 4 5 

X

Farmer John的最佳路线是:(0, 0),(-1, 0),(-2, 0),(-2, 1),(-2, 2),(-2, 3),(-2, 4),(-1, 4),(0, 4),(0, 3),(1, 3),(1, 2)。
同样附一张简图:
4 ******* . . . . 
3 * M . * . . . . 
Y 2 * . M B M . M . 
1 * M . M . M . . 
0 ***** . . . . . 
-1 . . . . . . . . 
-2-1 0 1 2 3 4 5 
X

打了个双向宽搜,结果把无用状态也扔了进去,爆空间了……

正解爆搜吧。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 int px[4]={1,0,-1,0};
17 int py[4]={0,1,0,-1};
18 const int N=1010;
19 int X,Y,n;
20 int ma[N][N];
21 int dis[N][N];
22 int vis[N][N];
23 struct node{
24     int x,y;
25     int col;
26 };
27 queue<node> pos;
28 int main(){
29     X=read();Y=read();
30     X+=500;
31     Y+=500;
32     n=read();
33     for(int i=1;i<=n;i++){
34         int x=read();int y=read();
35         ma[x+500][y+500]=1;
36     }
37     node st=(node){500,500,3};
38     node ed=(node){X,Y,2};
39     pos.push(st);
40     pos.push(ed);
41     vis[X][Y]=2;
42     while(!pos.empty()){
43         node tmp=pos.front();
44         pos.pop();
45         int tx=tmp.x,ty=tmp.y;
46         vis[tx][ty]=tmp.col;
47         for(int i=0;i<4;i++){
48             int dx=tx+px[i],dy=ty+py[i];
49             if(ma[dx][dy]==1) continue;
50             if(vis[dx][dy]){
51                 if(vis[dx][dy]!=tmp.col){
52                     printf("%d",dis[dx][dy]+dis[tx][ty]+1);
53                     return 0;
54                 }
55                 continue;
56             }
57             else{
58                 vis[dx][dy]=tmp.col;
59                 dis[dx][dy]=dis[tx][ty]+1;
60             }
61             pos.push((node){dx,dy,tmp.col});
62         }
63     }
64     return 0;
65 }

 


Description

与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返了。现在,Farmer John不得不去牧草专供商那里购买大量美味多汁的牧草,来满足他那N(1 <= N <= 100,000)头挑剔的奶牛。
所有奶牛都对FJ提出了她对牧草的要求:第i头奶牛要求她的食物每份的价钱不低于A_i(1 <= A_i <= 1,000,000,000),并且鲜嫩程度不能低于B_i(1 <= B_i <= 1,000,000,000)。商店里供应M(1 <= M <= 100,000)种不同的牧草,第i种牧草的定价为C_i(1 <= C_i <= 1,000,000,000),鲜嫩程度为D_i (1 <= D_i <= 1,000,000,000)。
为了显示她们的与众不同,每头奶牛都要求她的食物是独一无二的,也就是
说,没有哪两头奶牛会选择同一种食物。
Farmer John想知道,为了让所有奶牛满意,他最少得在购买食物上花多少
钱。
 

Input

* 第1行: 2个用空格隔开的整数:N 和 M
* 第2..N+1行: 第i+1行包含2个用空格隔开的整数:A_i、B_i
* 第N+2..N+M+1行: 第j+N+1行包含2个用空格隔开的整数:C_i、D_i

Output

* 第1行: 输出1个整数,表示使所有奶牛满意的最小花费。如果无论如何都无法满足所有奶牛的需求,输出-1
 

Sample Input

4 7
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4

Sample Output

12
 

Data Constraint

 
 

Hint

输出说明:
给奶牛1吃价钱为2的2号牧草,奶牛2吃价钱为4的3号牧草,奶牛3分到价钱
为2的6号牧草,奶牛4选择价钱为4的7号牧草,这种分配方案的总花费是12,为
所有方案中花费最少的。

 

  我的做法是拿个multiset维护牛的鲜美度,先按照价格将牛草排序,遍历草,将价格小于草的牛放进multiset,然后二分找最大的比草小的鲜美度弹出,这个牛和草就匹配了。

 1 #include<bits/stdc++.h>
 2 #include<set>
 3 using namespace std;
 4 int read(){
 5     int x=0,f=1;
 6     char c=getchar();
 7     while(!isdigit(c)){
 8         if(c=='-') f=-1;
 9         c=getchar();
10     }
11     while(isdigit(c)){
12         x=(x<<1)+(x<<3)+(c^48);
13         c=getchar();
14     }
15     return x*f;
16 }
17 const int N=1e5+10;
18 int n,m,tot;
19 struct node{
20     int mon,val;
21     bool operator <(const node &x)const{
22         return mon<x.mon;
23     }
24 }a[N],b[N];
25 multiset<int> q;
26 multiset<int> ::iterator it;
27 long long ans;
28 int main(){
29     n=read();m=read();
30     for(int i=1;i<=n;i++){
31         a[i].mon=read();
32         a[i].val=read();
33     }
34     sort(a+1,a+n+1);
35     for(int i=1;i<=m;i++){
36         b[i].mon=read();
37         b[i].val=read();
38     }
39     sort(b+1,b+m+1);
40     int j=1;
41     for(int i=1;i<=m;i++){
42         while(j<=n&&a[j].mon<=b[i].mon){
43             q.insert(a[j].val);
44             j++;
45         }
46         if(q.empty()) continue;
47         it=q.upper_bound(b[i].val);
48         if(it==q.begin()) continue;
49         it--;
50         q.erase(it);
51         ans+=b[i].mon;
52         tot++;
53     }
54     if(tot<n) printf("-1");
55     else printf("%lld",ans);
56     return 0;
57 }

Description

FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”。在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过。
今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie、Sylvia、Dora,登记人员就把这支队伍登记为BSD)。登记结束后,组委会将所有队伍的登记名称按字典序升序排列,就得到了他们的出场顺序。
FJ最近有一大堆事情,因此他不打算在这个比赛上浪费过多的时间,也就是说,他想尽可能早地出场。于是,他打算把奶牛们预先设计好的队型重新调整一下。
FJ的调整方法是这样的:每次,他在原来队列的首端或是尾端牵出一头奶牛,把她安排到新队列的尾部,然后对剩余的奶牛队列重复以上的操作,直到所有奶牛都被插到了新的队列里。这样得到的队列,就是FJ拉去登记的最终的奶牛队列。
接下来的事情就交给你了:对于给定的奶牛们的初始位置,计算出按照FJ的调整规则所可能得到的字典序最小的队列。
 

Input

* 第1行: 一个整数:N
* 第2..N+1行: 第i+1行仅有1个'A'..'Z'中的字母,表示队列中从前往后数第i头奶牛名字的首字母

Output

* 第1..??行: 输出FJ所能得到的字典序最小的队列。每行(除了最后一行)输出恰好80个'A'..'Z'中的字母,表示新队列中每头奶牛姓名的首字母
 

Sample Input

6
A
C
D
B
C
B

Sample Output

ABCBCD
 

Data Constraint

 
 

Hint

【样例解释】
操作数 原队列 新队列
#1 ACDBCB  
#2 CDBCB A
#3 CDBC AB
#4 CDB ABC
#5 CD ABCB
#6 D ABCBC
#7   ABCBCD

贪心。

如果两边字母一样,就往里面找,直到两个字母不一样,先输出字典序小的那一边。

但这样会T。

优化一下,考虑这样一个串:BBDCBB,因为外面4个b都是一样的,所以可以判断一下,上面的那个操作做完以后,看下一个字母是不是和上面那个一样,如果是就一起输出,这样就是O(n)的了。

posted @ 2019-11-08 15:43  Nelson992770019  阅读(737)  评论(0编辑  收藏  举报