2017-10-03-afternoon

P100

zhx

竞赛时间:??????????:??-??:??

题目名称

a

b

c

名称

a

b

c

输入

a.in

b.in

c.in

输出

a.out

b.out

c.out

每个测试点时限

1s

1s

1s

内存限制

256MB

256MB

256MB

测试点数目

6

100 或 200

10

每个测试点分值

16 或者 17

1 或 0.5

10

是否有部分分

题目类型

传统

传统

传统

注意事项(请务必仔细阅读):

P100 zhxa

T1 a

【问题描述】

你是能看到第一题的 friends 呢。

——hja

给你一个只有小括号和中括号和大括号的括号序列,问该序列是否合法。

【输入格式】

一行一个括号序列。

【输出格式】

如果合法,输出 OK,否则输出 Wrong。

【样例输入】

[(])

【样例输出】

Wrong

【数据范围与规定】

对于70%的数据,1 ≤N≤ 100。

对于100%的数据,1 ≤N≤ 10000,所有单词由大写字母组成。

栈模拟

 1 #include <cstring> 
 2 #include <cstdio>
 3 
 4 const int N(10005);
 5 char s[N],stack[N];
 6 int top;
 7 
 8 int Presist()
 9 {
10     freopen("a.in","r",stdin);
11     freopen("a.out","w",stdout);
12     scanf("%s",s+1);  int n=strlen(s+1);
13     if(n&1) { printf("Wrong"); return 0; }
14     for(int i=1; i<=n; ++i)
15     {
16         if(s[i]=='[') stack[++top]='[';
17         else if(s[i]=='(') stack[++top]='(';
18         else if(s[i]==']')
19              {
20                  if(!top||stack[top--]!='[')
21                  {
22                      printf("Wrong");
23                      return 0;
24                 }
25              }
26         else if(s[i]==')')
27              {
28                  if(!top||stack[top--]!='(')
29                  {
30                      printf("Wrong");
31                      return 0;
32                 }
33              }
34     }
35     printf("OK");
36     return 0;
37 }
38 
39 int Aptal=Presist();
40 int main(int argc,char**argv){;}
AC

T2 b

【问题描述】

你是能看到第二题的 friends 呢。

——laekov

Yjq 想要将一个长为 宽为 的矩形棺材(棺材表面绝对光滑,所以棺材可以任意的滑动)拖过一个型墓道。

如图所示,L 型墓道两个走廊的宽度分别是 ,呈 90°,并且走廊的长度远大于

现在 Hja 想知道对于给定的a ,  b, l,最大的 是多少,如果无论如何棺材都不可能通过,则输出"My poor head =("

【输入格式】

第一行三个用空格分隔的整数a , b , l,意义如题目所示。

【输出格式】

输出最大的可能的 w,保留七位小数,如果无论如何棺材都不可能通过,则输出"My poor head =("。

【样例输入 1】

2 2 1

【样例输出 1】

1.0000000

【样例输入 2】

2 2 2

【样例输出 2】

2.0000000

【样例输入 3】

2 2 3

【样例输出 3】

1.3284271

【样例输入 4】

2 2 6

【样例输出 4】

My poor head =(

【数据范围与规定】

对于100%的数据,1 ≤  a,b  l,≤ 104

 

设直线解析式为 y=(-n/m)* x+n

整理,得:n * x + m * y - n * m = 0

点(b,a)到直线的距离为:|  b * n + a * m - n * m | / L

(L : 根号下(n^2 + m^2)=L)

棺材能够在这里拐弯

直观上感受就是棺材拐弯的全程不被点(b,a)卡住

所以 最优解 是  b * n + a * m - n * m / L 的最小值

为什么这里把绝对值去掉?

因为 当式子<0 时,直线到了点的右上方,就是不合法解,此时棺材不能通过

单峰函数求最小值,三分法每次去掉大的一部分

注意特判直接横着/竖着就能拖过去的情况

 

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 
 5 using namespace std;
 6 const double eps=1e-9;
 7 
 8 int a,b,l;
 9 
10 double f(double n)
11 {
12     double m=sqrt(1.0*l*l-n*n);
13     return (b*n+a*m-n*m)/l;
14 }
15 
16 int main()
17 {
18     freopen("b.in","r",stdin);
19     freopen("b.out","w",stdout);
20     scanf("%d%d%d",&a,&b,&l);
21     if(a>=l && b>=l) { printf("%d.0000000",l); return 0; }
22     if(a>=l) { printf("%d.0000000",b); return 0; }
23     if(b>=l) { printf("%d.0000000",a); return 0; }
24     double L=0,R=l,ans=-1e18,mid1,mid2,t1,t2;
25     int T=100;
26     while(T--)
27     {
28         mid1=(R-L)/3+L; mid2=L+R-mid1;
29         t1=f(mid1); t2=f(mid2);
30         if(t1<0 || t2<0) { printf("My poor head =("); return 0; }
31         if(t1<t2) ans=t1,R=mid2;
32         else ans=t2,L=mid1;
33     }
34     printf("%.7lf",ans);
35 }
AC

T3 c

【问题描述】

你是能看到第三题的 friends 呢。

——aoao

树是个好东西,删掉树一条边要的代价,随便再加一条边有的代价,求最小的代价把树变成环。

【输入格式】

第一行一个整数 N,代表树的点数。

接下来 N− 1行,每行两个数代表树的一条边。

【输出格式】

一行一个整数代表答案。

【样例输入】

4

1 2

2 3

2 4

【样例输出】

3

【数据规模与约定】

对于30%的数据,1 ≤N ≤ 10。对于60%的数据,1 ≤N ≤ 1000。

对于100%的数据,1 ≤ N≤ 100000。

 1 #include <cstdio>
 2 #include <map>
 3 
 4 inline void read(int &x)
 5 {
 6     x=0; register char ch=getchar();
 7     for(; ch>'9'||ch<'0'; ) ch=getchar();
 8     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
 9 }
10 
11 const int N(100005);
12 
13 std::map<int,bool>cut[N];
14 
15 int n,cnt[N],ans,tmp;
16 int head[N],sumedge;
17 struct Edge {
18     int v,next;
19     Edge(int v=0,int next=0):v(v),next(next){}
20 }edge[N<<1];
21 inline void ins(int u,int v)
22 {
23     cnt[u]++; cnt[v]++;
24     edge[++sumedge]=Edge(v,head[u]); head[u]=sumedge;
25     edge[++sumedge]=Edge(u,head[v]); head[v]=sumedge;
26 }
27 
28 int tim,dfn[N];
29 inline void Cutedge(int u)
30 {
31     int maxx=-1,pos;
32     for(int v,i=head[u]; i; i=edge[i].next)
33     {
34         v=edge[i].v;
35         if(cnt[v]>maxx&&!cut[u][v]&&!cut[v][u]) maxx=cnt[v],pos=v;
36     }
37     cnt[pos]--; cut[u][pos]=cut[pos][u]=1;
38 }
39 void DFS(int u)
40 {
41     dfn[u]=++tim;
42     for(int v,i=head[u]; i; i=edge[i].next)
43     {
44         v=edge[i].v;
45         if(!cut[u][v]&&!cut[v][u]&&!dfn[v]) DFS(v);
46     }
47 }
48 
49 int Presist()
50 {
51 //    freopen("c.in","r",stdin);
52 //    freopen("c.out","w",stdout);
53     read(n);
54     for(int u,v,i=1; i<n; ++i)
55         read(u),read(v),ins(u,v);
56     for(int i=1; i<=n; ++i)
57       for(; cnt[i]>2; cnt[i]--)
58         Cutedge(i),ans++;
59     for(int i=1; i<=n; ++i)
60         if(!dfn[i]) DFS(i),ans++;
61     printf("%d
",ans);
62     return 0;
63 }
64 
65 int Aptal=Presist();
66 int main(int argc,char**argv){;}
30分 莫名WA

贪心处理每个节点,当一个点的度数>2时,一定需要删去一条父边,这个点对答案的贡献是 cnt[i]-2<<1,

要求是一条链,所以多出的边都应删去,一个环的总边数不变,删去的边一定会在累加上,所以*2

 1 #include <cstdio>
 2 
 3 inline void read(int &x)
 4 {
 5     x=0; register char ch=getchar();
 6     for(; ch>'9'||ch<'0'; ) ch=getchar();
 7     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
 8 }
 9 
10 const int N(100005);
11 
12 int n,cnt[N],ans;
13 int head[N],sumedge;
14 struct Edge {
15     int v,next;
16     Edge(int v=0,int next=0):v(v),next(next){}
17 }edge[N<<1];
18 inline void ins(int u,int v)
19 {
20     cnt[u]++; cnt[v]++;
21     edge[++sumedge]=Edge(v,head[u]); head[u]=sumedge;
22     edge[++sumedge]=Edge(u,head[v]); head[v]=sumedge;
23 }
24 
25 void DFS(int u,int pre)
26 {
27     for(int v,i=head[u]; i; i=edge[i].next)
28     {
29         v=edge[i].v;
30         if(v==pre) continue;
31         DFS(v,u);
32         if(cnt[v]>2)
33         {
34             cnt[u]--;
35             ans+=cnt[v]-2<<1;
36         }
37     }
38 }
39 
40 int Presist()
41 {
42     freopen("c.in","r",stdin);
43     freopen("c.out","w",stdout);
44     read(n);
45     for(int u,v,i=1; i<n; ++i)
46         read(u),read(v),ins(u,v);
47     for(int i=1; i<=n; ++i)
48         if(cnt[i]==1) { DFS(i,0); break; }
49     printf("%d
",ans+1);
50     return 0;
51 }
52 
53 int Aptal=Presist();
54 int main(int argc,char**argv){;}
AC
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/7658564.html