2020-07-05 熱身訓練賽(五)

A.(Gym-12483A)

 

B.(Gym-12483B)

C.構造圖(Gym-12483C)

題意:給出一個樹,要求寫出每個節點的座標,使得相鄰節點之間的距離爲1,並且任何一對節點之間的距離最少爲$10^{-4}$,相鄰節點之間的距離與1的絕對誤差最多爲$10^{-6}$,不連接在同一節點的邊之間的距離至少爲$10^{-6}$,座標的絕對值不超過$3000$。

解:分配邊轉化爲分配角度$\theta$,那麼點的座標就是$(x+cos\theta,y+sin\theta)$,爲了避免交叉,利用樹的結構進行dfs,角度按照dfs的順序增大,這樣就可以保證邊不重疊了,實際上不用刻意的研究$10^{-4}和10^{-6}$,可以認爲這兩個數字就表示無窮小,也就是點重疊,邊交叉的情況。比賽的時候沒認真考慮邊交叉,就用了bfs,後來隊友也寫了一個,寫的dfs,但也wa了。賽後去看了一下別人的代碼,才突然意識到這個問題。隊友寫的dfs我也看了一下,發現裏面出了一個極小無比的錯誤,改掉就過了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#define maxn 1001
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
using namespace std;
int num,head[maxn];
struct node{
    int to,pre;
}e[maxn*2];

void Insert(int from,int to){
    e[++num].to=to;
    e[num].pre=head[from];
    head[from]=num;
}

struct point{
    double x,y;
}p[maxn];

int n;
double Eps;
bool vis[maxn];

int cnt=-1;
void dfs(int now){
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(!vis[to]){
            vis[to]=1;
            cnt++;
            p[to].x=p[now].x+cos(Eps*cnt);
            p[to].y=p[now].y+sin(Eps*cnt);
            dfs(to);
        }
    }
}
int main(){
    scanf("%d",&n);
    Eps=(double)M_PI/(double)1000;
    int x,y;
    for(int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        Insert(x,y);Insert(y,x);
    }
    p[1].x=0;p[1].y=0;
    vis[1]=1;
    dfs(1);
    for(int i=1;i<=n;i++){
        printf("%.15f %.15f\n",(double)p[i].x,(double)p[i].y);
    }
    return 0;
}

 

D.(Gym-12483D)

E.(Gym-12483E)

F.(Gym-12483F)

G.構造障礙(Gym-12483G)

題意:在一個平面上有一個小球,許多障礙物和一個洞(洞的座標爲(0,0)),將平板向一個方向傾斜,就可以使小球向這個方一直滾動,直到遇到障礙物或者進洞。題目給出一個包含LRUD的字符串,表示平板傾斜的方向序列,要求根據這個序列設計一種障礙物的擺放方法,使小球最後能順利進洞,不能滿足條件的輸出impossible。

解:規定小球從(0,0)開始滾動,最後根據最終的位置應該在(0,0),把所有的點進行平移。可以先判斷能夠產生impossible的情況,impossible實際上就是中途進洞,因爲最後一步移動要把小球移動到洞裏,所以如果有LRL,RLR,UDU,DUD這四種情況出現在最後三次操作中,就直接輸出impossible了。求路徑時,如果有RLRL這類情況,就可以只設置左右兩個障礙,如果出現RU這類情況,就把小球向U移兩格,設置新的障礙。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 10010
using namespace std;
char s[21];
int n,cnt;
bool flag;
struct node{
    int x,y;
    bool operator == (const node u)const{
        if(x==u.x&&y==u.y)return 1;
        return 0;
    }
    bool operator < (const node u)const{
        if(x!=u.x)return x<u.x;
        return y<u.y;
    } 
}ans[maxn];
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    if(n>=3){
        if(!strcmp(s+n-2,"LRL"))flag=1;
        if(!strcmp(s+n-2,"RLR"))flag=1;
        if(!strcmp(s+n-2,"UDU"))flag=1;
        if(!strcmp(s+n-2,"DUD"))flag=1;
    }
    if(flag){
        puts("impossible");
        return 0;
    }
    int d=1;
    int x=0,y=0;
    for(int i=1;i<=n;i++){
        if(s[i]=='R'){
            x=d;
            ans[++cnt]={x+1,y};
        }
        if(s[i]=='L'){
            x=-d;
            ans[++cnt]={x-1,y};
        }
        if(s[i]=='U'){
            y=d;
            ans[++cnt]={x,y+1};
        }
        if(s[i]=='D'){
            y=-d;
            ans[++cnt]={x,y-1};
        }
        if(i+1<=n){
            if(s[i]=='L'&&s[i+1]=='R');
            else if(s[i]=='R'&&s[i+1]=='L');
            else if(s[i]=='U'&&s[i+1]=='D');
            else if(s[i]=='D'&&s[i+1]=='U');
            else d+=2;
        }
    }
    printf("%d %d\n",-x,-y);
    sort(ans+1,ans+cnt+1);
    n=unique(ans+1,ans+cnt+1)-ans-1;
    printf("%d\n",n);
    for(int i=1;i<=n;i++){
        printf("%d %d\n",ans[i].x-x,ans[i].y-y);
    }
    return 0;
}

 

H.(Gym-12483H)

題意:一共有n個位置,可以填入0或1,如果相鄰兩個數字不同,就稱爲有一個change,題目中指定b個位置只能爲0(約定第一個位置不指定,最後一個位置指定),其它位置填0或者1,使得恰好有c個change,要求寫出一種符合要求的01串。

解:可以發現如果在兩個0之間填1,無論如何都會增加偶數個change,而如果在第一個位置填了1,那麼無論如何都會增加奇數個1。所以可以通過c的奇偶性來判斷第一個位置應該填的數。然後根據剩下的需要滿足的change數,來順次填不一樣的數字。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 500010
using namespace std;
int n,c,b,a[maxn];
int main(){
    scanf("%d%d%d",&n,&c,&b);
    memset(a,-1,sizeof(a));
    int x;
    for(int i=1;i<=b;i++){
        scanf("%d",&x);
        a[x]=0;
    }
    if(c%2==1){a[1]=1;}
    else a[1]=0;
    for(int i=2;i<=n;i++){
        if(a[i]==-1){
            if(c>0)a[i]=!a[i-1];
        }
        if(a[i]!=a[i-1])c--;
        if(c<=0)break;
    }
    for(int i=1;i<=n;i++){
        if(a[i]==-1)a[i]=0;
        printf("%d",a[i]);
    }
    puts("");
    return 0;
}

 

I.(Gym-12483I)

J.(Gym-12483J)

K.(Gym-12483K)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章