1. 程式人生 > >10.1綜合強化刷題 Day3 afternoon

10.1綜合強化刷題 Day3 afternoon

algo closed 單詞 cnblogs 分代 括號序列 section 技術 事情

                      競賽時間:??????????:??-??:??

題目名稱

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

是否有部分分

題目類型

傳統

傳統

傳統

a

【問題描述】

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

——hja

給你一個只有小括號和中括號和大括號的括號序列,問該序列是否合法。

【輸入格式】

一行一個括號序列。

【輸出格式】

如果合法,輸出

OK,否則輸出 Wrong。

【樣例輸入】

[(])

【樣例輸出

Wrong

【數據範圍與規定】

對於70%的數據,1 ≤ N≤ 100。

對於100%的數據,1 ≤ N≤ 10000,所有單詞由大寫字母組成。

簡單粗暴的棧模擬

技術分享
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10010
using namespace
std; char ch[N]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); cin>>ch; int l=strlen(ch); int top=0;bool flag=false; if(l%2!=0) printf("Wrong"); else { for(int i=0;i<l;i++) { if(ch[i]==(||ch[i]==[) top++; else { if(ch[i]==]) { if(!top||ch[i-1]==() {flag=true; break;} if(ch[i-1]==[) top--; } else { if(!top||ch[i-1]==[) {flag=true; break;} if(ch[i-1]==() top--; } } } if(!flag) printf("OK"); else printf("Wrong"); } return 0; }
AC代碼

b

【問題描述】

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

——laekov

Yjq 想要將一個長為l 寬為 w的矩形棺材(棺材表面絕對光滑,所以棺材可以任意的滑動)拖過一個 L 型墓道。

如圖所示,L 型墓道兩個走廊的寬度分別是a b,呈 90°,並且走廊的長度遠大於l

現在 Hja 想知道對於給定的 a,b l, ,最大的 w是多少,如果無論如何棺材都不可能通過,則輸出"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

哈哈,只輸出沒有解的情況能得38.5、、、

技術分享
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a,b,l;
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    a=read(),b=read(),l=read();
    printf("My poor head =(");
    return 0;
}
38.5特判

解析幾何+三分求單峰函數最值

技術分享

設直線解析式為 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)

//特判三種情況,一種是怎麽找都能拖過去的(w最大等於l),一種是可以橫著過去的(w要比b小才能過去),一種是可以豎著過去的(w要比a小才能過去)
//進行三分找最優解
//對於這個棺材我們可以知道解析式為n*x+m*y-n*m=0,(b,a)這個點到直線的距離為|n*b+m*a-n*m|/l
//我們知道我們要使棺材能過去,必須要是他在任何地方都能過去,也就是說這個棺材的w要比這個點到直線的距離的最小值小或者等於
//這樣的話,我們就轉換成單峰函數求最值,采用三分法
//三分法?三分法的思路與二分法很類似,不過其用途沒有那麽廣泛,主要用於求單峰函數的極值。
while(t<100)//對於實數類型的三分或二分直接分100次就夠了

//當最小值為負數的時候即為無論怎樣都過不去的時候,直接輸出My poor head =(

技術分享
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a,b,l,t;
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
double work(double n)
{
    double m=sqrt(1.0*l*l-n*n); 
    return (m*a+b*n-n*m)/l;//求出點到直線的距離 
}
int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    a=read(),b=read(),l=read();
    if(a>=l&&b>=l) {printf("%d.0000000",l); return 0;}
    if(a>=l) {printf("%d.0000000",b); return 0;}
    if(b>=l) {printf("%d.0000000",a); return 0;}
    //特判三種情況,一種是怎麽找都能拖過去的(w最大等於l),一種是可以橫著過去的(w要比b小才能過去),一種是可以豎著過去的(w要比a小才能過去) 
    double L=0,R=l,ans=-1e8,mid1,mid2,t1,t2;
    //進行三分找最優解
    //對於這個棺材我們可以知道解析式為n*x+m*y-n*m=0,(b,a)這個點到直線的距離為|n*b+m*a-n*m|/l 
    //我們知道我們要使棺材能過去,必須要是他在任何地方都能過去,也就是說這個棺材的w要比這個點到直線的距離的最小值小或者等於
    //這樣的話,我們就轉換成單峰函數求最值,采用三分法
    //三分法?三分法的思路與二分法很類似,不過其用途沒有那麽廣泛,主要用於求單峰函數的極值。 
    while(t<100)//對於實數類型的三分或二分直接分100次就夠了 
    {
        t++;
        mid1=(R-L)/3+L,mid2=R+L-mid1;//三分 
        t1=work(mid1),t2=work(mid2);
        if(t1<0||t2<0) {printf("My poor head =("); return 0;}//當最小值為負數的時候即為無論怎樣都過不去的時候 
        if(t1<t2) ans=t1,R=mid2;
        else ans=t2,L=mid1;
    }
    printf("%.7lf",ans);
    return 0;
}
AC代碼

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。

明明寫了個60分的部分分,結果node結構體裏面的數不知道怎麽改,弄出負數來了,然後就只得了30分

技術分享
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1010
using namespace std;
int n,x,y,s,in[N],sum,ans,q[N][N];
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
struct Node
{
    int num,w,s;
}node[N][N];
int cmp(Node a,Node b){return a.w>b.w;}
int main()
{
//    freopen("c.in","r",stdin);
//    freopen("c.out","w",stdout);
    n=read();
    for(int i=1;i<n;i++)
    {
        x=read(),y=read();
        in[x]++,in[y]++;
        q[x][in[x]]=y;
        q[y][in[y]]=x;
    }
    for(int i=1;i<=n;i++)
      for(int j=1;j<=in[i];j++)
        node[i][j].num=q[i][j],node[i][j].w=in[q[i][j]],node[i][q[i][j]].s=j;
    for(int i=1;i<=n;i++)
     if(in[i]>2)
     {
        for(int j=1;j<=in[i];j++)
        {
            y=node[i][j].num;
            node[y][node[y][i].s].w=2;
        //    node[y][node[y][i].s].num;
        } 
        sort(node[i]+1,node[i]+1+in[i],cmp);
        sum=in[i]-2,in[i]=2,s=1;
         while(sum)
         {
             y=node[i][s].num,in[y]--;
            for(int j=1;j<=in[y]+1;j++)
            {
                x=node[y][j].num;
                node[x][node[x][y].s].w--;
            }    
             ans+=2,sum--,s++;
         }
     }
    for(int i=1;i<=n;i++) printf("%d ",in[i]);
    ans+=2*n;sum=0;
    for(int i=1;i<=n;i++)
     sum+=in[i];
    ans-=sum;ans/=2;
    printf("\n%d",ans);
    return 0;
}
30分代碼

正解樹形dp,劉大佬用亂搞A掉的,由於本蒟蒻不會dp,所以聽的亂搞的思路

我們先把原來的樹變成一條鏈,然後變成鏈的代價+1以後就是總代價。怎樣求變成鏈的代價呢?我們搜索整棵樹,我們隨便找一個入度為1的節點為根節點,然後搜索整棵樹,當一個節點的度數>2的時候,我們就要對其進行刪邊,刪去除那兩條邊以外的邊由於我們要變成一條鏈,因此我們在刪完邊以後還要在建相同數量的邊(原樹的邊的條數為n-1,鏈的條數也為n-1)因此我們這個地方要乘2,我們把這條邊刪去,那麽他的父親節點的入讀就-1

技術分享
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100010
using namespace std;
int n,x,y,root,tot,ans,in[N],head[N<<2];
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
struct Edge
{
    int to,next,from;
}edge[N<<2];
int add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
void dfs(int x,int fa)
{
    for(int i=head[x];i;i=edge[i].next)
    {
        int t=edge[i].to;
        if(t==fa) continue;
        dfs(t,x);
        if(in[t]>2)
        {
            in[x]--;
            ans+=(in[t]-2)*2;
        }
    }
}
int main()
{
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    n=read();
    for(int i=1;i<n;i++) 
    {
        x=read(),y=read();
        add(x,y),add(y,x);
        in[x]++,in[y]++;    
    }
    for(int i=1;i<=n;i++)
      if(in[i]==1) {root=i; break;}
    dfs(root,-1);
    printf("%d",ans+1);
    return 0;
 } 
AC代碼

                技術分享

                      距 NOIp2017 還剩 28 天

   你可以做的事情還有很多,即使到最後一秒也不要放棄,因為不到結束的那一刻誰也不知道結果會怎樣。

10.1綜合強化刷題 Day3 afternoon