10.1綜合強化刷題 Day3 afternoon
競賽時間:????年??月??日??:??-??:??
題目名稱 |
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
給你一個只有小括號和中括號和大括號的括號序列,問該序列是否合法。
【輸入格式】
一行一個括號序列。
【輸出格式】
如果合法,輸出
【樣例輸入】
[(])
【樣例輸出
Wrong
【數據範圍與規定】
對於70%的數據,1 ≤ N≤ 100。
對於100%的數據,1 ≤ N≤ 10000,所有單詞由大寫字母組成。
簡單粗暴的棧模擬
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 10010 using namespaceAC代碼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; }
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