国庆 day 3 下午

 

a
【问题描述】
      你是能看到第一题的 friends 呢。
                      ——hja
    给你一个只有小括号和中括号和大括号的括号序列,问该序列是否合法。
【输入格式】
  一行一个括号序列。
【输出格式】
  如果合法,输出 OK,否则输出 Wrong。
【样例输入】
  [(])
【样例输出】
  Wrong
【数据范围与规定】
  对于70%的数据,1 ≤n≤ 100。
  对于100%的数据,1 ≤ n≤ 10000,所有单词由大写字母组成。
P100 zhxb
思路:栈维护一下。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
string s;
char stack[10100];
int top,m1,m2,m3;
int main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    cin>>s;
    int len=s.length();
    for(int i=0;i<len;i++){
        if(s[i]=='(') {m1++;stack[top++]=s[i];}
        if(s[i]=='[') {m2++;stack[top++]=s[i];}
        if(s[i]=='{') {m3++;stack[top++]=s[i];}
        else if(s[i]==')'){
            if(!m1){cout<<"Wrong";return 0;}
            else if(stack[top-1]!='('){cout<<"Wrong";return 0;}
            else{top--;m1--;}
        }
        else if(s[i]==']'){
            if(!m2){cout<<"Wrong";return 0;}
            else if(stack[top-1]!='['){cout<<"Wrong";return 0;}
            else {top--;m2--;}
        }
        else if(s[i]=='}'){
            if(!m3){cout<<"Wrong";return 0;}
            else if(stack[top-1]!='{'){cout<<"Wrong";return 0;}
            else {top--;m3--;}
        }
    }
    if(top||m1||m2||m3) cout<<"Wrong";
    else cout<<"OK";
}
View Code

 

b
【问题描述】
      你是能看到第二题的 friends 呢。
                      ——laekov
    Yjq 想要将一个长为l宽为w的矩形棺材(棺材表面绝对光滑,所以棺材可
  以任意的滑动)拖过一个 L 型墓道。
    如图所示,L 型墓道两个走廊的宽度分别是a和b,呈 90°,并且走廊的长
  度远大于?。
    现在 Hja 想知道对于给定的a,b,l,最大的?是多少,如果无论如何棺材都
  不可能通过,则输出"My poor head =("
【输入格式】
  第一行三个用空格分隔的整数a,b,l,意义如题目所示。
【输出格式】
  输出最大的可能的?,保留七位小数,如果无论如何棺材都不可能通过,则
  输出"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 ≤ 10 4
  P100 zhxc

 以下解题思路来自xxy大佬的博客

设直线解析式为 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 * n - a * m + n * m 的最大值

然后不知道为啥求了个

b * n + a * m - n *m 的最小值

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

式子最小值<0 时无解

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-9;
int a,b,l;
double L=0,R=1;
double ans=0x7f7f7f7f;
double mid1,mid2,t1,t2;
double f(double n){
    double m=sqrt(1.0*l*l-n-n);
    if(n*m>a*n+b*m)    return -1;
    return (b*m+a*n-n*m)/l;
}
int main(){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%d%d%d",&a,&b,&l);
    if(a>=1&&b>=1){
        printf("%d.0000000",l);
        return 0;
    }
    if(a>=l){
        printf("%d.0000000",b);
        return 0;
    }
    if(b>=1){
        printf("%d.0000000",a);
        return 0;
    }
    int t=100;
    while(t--){
        mid1=(R-L)/3+L;
        mid2=L+R-mid1;
        t1=f(mid1);
        t2=f(mid2);
        if(t1<0||t2<0){
            printf("My poor head =(");
            return 0;
        }
        if(t1<t2){
            ans=min(ans,t1);
            R=mid2;
        }
        else{
            ans=min(ans,t2);
            L=mid1;
        }
    }
    printf("%.7lf",ans);
}
View Code

 


c
【问题描述】
      你是能看到第三题的 friends 呢。
                      ——aoao
    树是个好东西,删掉树一条边要 1 的代价,随便再加一条边有 1 的代价,求
  最小的代价把树变成环。
【输入格式】
  第一行一个整数n,代表树的点数。
  接下来n − 1行,每行两个数代表树的一条边。
【输出格式】
  一行一个整数代表答案。
【样例输入】
  4
  1 2
  2 3
  2 4
【样例输出】
  3
【数据规模与约定】
  对于30%的数据,1≤n≤10。
  对于60%的数据,1 ≤ n ≤ 1000。
  对于100%的数据,1 ≤ n ≤ 100000。

思路:贪心。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,tot,ans,root;
int into[MAXN];
int to[MAXN*2],net[MAXN*2],head[MAXN*2];
void add(int u,int v){
    to[++tot]=v;net[tot]=head[u];head[u]=tot;
    to[++tot]=u;net[tot]=head[v];head[v]=tot;
}
void dfs(int now,int fa){
    for(int i=head[now];i;i=net[i])
        if(to[i]!=fa){
            dfs(to[i],now);
            if(into[to[i]]>2){
                into[now]--;
                ans+=(into[to[i]]-2)*2;
            }
        }
}
int main(){
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        into[u]++;
        into[v]++;
    }
    root=1;
    for(int i=1;i<=n;i++)
        if(into[i]==1){
            root=i;
            break;
        }
    dfs(root,-1);
    cout<<ans+1;
}
/*
8
1 2
1 3
3 4
3 5
4 6
4 7
4 8
3
*/
View Code

 

posted @ 2017-10-10 08:15  一蓑烟雨任生平  阅读(201)  评论(0编辑  收藏  举报