zoukankan      html  css  js  c++  java
  • 2016-2017 CT S03E06: Codeforces Trainings Season 3 Episode 6(8/13)

    2016-2017 CT S03E06: Codeforces Trainings Season 3 Episode 6

    比赛连接:

    http://codeforces.com/gym/101124/

    代码地址

    http://git.oschina.net/qscqesze/Acm/tree/master/contest/2016-2017 CT S03E06 Codeforces Trainings Season 3 Episode 6?dir=1&filepath=contest%2F2016-2017+CT+S03E06+Codeforces+Trainings+Season+3+Episode+6&oid=25d818184806af64cbeb5a0e6235eeb6f1252004&sha=bdab61c2245418e3be90bd32b6dccc4df0995d8f

    Problem A. The Baguette Master

    题意

    给你一个四边形,让你给这个四边形加上一个长度为2的框,问你这个框的最大的周长是多少。

    题解

    框最多就往上移动或者往下移动,那么2^4枚举一下,然后取一个最大值就好了。

    不过我队友好像不是这样写的。。。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const double pi=acos(-1);
    const double eps=1e-9;
    
    int main()
    {
        double tha,thb,thc,thd,w,ab,bc,cd,da,ac,ans,AB,BC,CD,DA,AC,BD;
        scanf("%lf%lf%lf%lf%lf%lf",&w,&ab,&bc,&cd,&da,&ac);
        thb=acos((ab*ab+bc*bc-ac*ac)/(2.0*ab*bc));
        thd=acos((cd*cd+da*da-ac*ac)/(2.0*cd*da));
        tha=acos((ab*ab+ac*ac-bc*bc)/(2.0*ab*ac))+acos((da*da+ac*ac-cd*cd)/(2.0*da*ac));
        thc=acos((bc*bc+ac*ac-ab*ab)/(2.0*bc*ac))+acos((cd*cd+ac*ac-da*da)/(2.0*cd*ac));
        if(fabs(tha-pi)<eps)
        {
            BC=bc+(w*cos(thb)/sin(thb)+w*cos(thc)/sin(thc));
            CD=cd+(w*cos(thc)/sin(thc)+w*cos(thd)/sin(thd));
            BD=ab+da+(w*cos(thd)/sin(thd)+w*cos(thb)/sin(thb));
            ans=CD+BD+BC+2.0*(w/sin(thb)+w/sin(thc)+w/sin(thd));
        }
        else if(fabs(thb-pi)<eps)
        {
            CD=cd+(w*cos(thc)/sin(thc)+w*cos(thd)/sin(thd));
            DA=da+(w*cos(thd)/sin(thd)+w*cos(tha)/sin(tha));
            AC=ab+bc+(w*cos(tha)/sin(tha)+w*cos(thc)/sin(thc));
            ans=CD+DA+AC+2.0*(w/sin(tha)+w/sin(thc)+w/sin(thd));
        }
        else if(fabs(thc-pi)<eps)
        {
            AB=ab+(w*cos(tha)/sin(tha)+w*cos(thb)/sin(thb));
            DA=da+(w*cos(thd)/sin(thd)+w*cos(tha)/sin(tha));
            BD=bc+cd+(w*cos(thb)/sin(thb)+w*cos(thd)/sin(thd));
            ans=AB+BD+DA+2.0*(w/sin(tha)+w/sin(thb)+w/sin(thd));
        }
        else if(fabs(thd-pi)<eps)
        {
            AB=ab+(w*cos(tha)/sin(tha)+w*cos(thb)/sin(thb));
            BC=bc+(w*cos(thb)/sin(thb)+w*cos(thc)/sin(thc));
            AC=cd+da+(w*cos(thc)/sin(thc)+w*cos(tha)/sin(tha));
            ans=AB+BC+AC+2.0*(w/sin(tha)+w/sin(thb)+w/sin(thc));
        }
        else
        {
            AB=ab+(w*cos(tha)/sin(tha)+w*cos(thb)/sin(thb));
            BC=bc+(w*cos(thb)/sin(thb)+w*cos(thc)/sin(thc));
            CD=cd+(w*cos(thc)/sin(thc)+w*cos(thd)/sin(thd));
            DA=da+(w*cos(thd)/sin(thd)+w*cos(tha)/sin(tha));
            ans=AB+BC+CD+DA+2.0*(w/sin(tha)+w/sin(thb)+w/sin(thc)+w/sin(thd));
        }
      //  cout<<tha<<" "<<thb<<" "<<thc<<" "<<thd<<endl;
      //  cout<<tha+thb+thc+thd<<endl;
        printf("%.12f
    ",ans);
        return 0;
    }
    

    Problem C. Old Chess Sets

    题意

    给你两个集合,问你这两个集合加起来,能不能构成国际象棋的32个棋子。

    题解

    签到题

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int k1,k2;
    int mp[2][35];
    int num[35];
    int getid(string s){
        if(s=="black")return 0;
        if(s=="white")return 1;
        if(s=="king")return 0;
        if(s=="queen")return 1;
        if(s=="bishop")return 2;
        if(s=="knight")return 3;
        if(s=="rook")return 4;
        if(s=="pawn")return 5;
    }
    vector<string>ans1,ans2;
    int main()
    {
        num[0]=1,num[1]=1,num[2]=2,num[3]=2,num[4]=2,num[5]=8;
        memset(mp,0,sizeof(mp));
        scanf("%d%d",&k1,&k2);
        for(int i=0;i<k1;i++){
            string s1,s2;
            cin>>s1>>s2;
            mp[getid(s1)][getid(s2)]++;
        }
        int flag = 0;
        for(int i=0;i<k2;i++){
            string s1,s2;
            cin>>s1>>s2;
            if(mp[getid(s1)][getid(s2)]<num[getid(s2)])
            {
                mp[getid(s1)][getid(s2)]++;
                ans1.push_back(s1);
                ans2.push_back(s2);
            }
        }
        if(ans1.size()+k1==32){
            for(int i=0;i<ans1.size();i++)
                cout<<ans1[i]<<" "<<ans2[i]<<endl;
        }
        else{
            cout<<"impossible"<<endl;
        }
    }
    

    Problem D. Checkmate with Bishop and Knight

    题意

    给你一个国际象棋的局势,问你应该下哪一步,才能将死对面。

    题解

    直接暴力枚举就好了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    pair<int,int> pos(string s){
        return make_pair(s[0]-'a',s[1]-'1');
    }
    pair<int,int> bishop,knight,wking,bking;
    int mp[10][10];
    int dkx[8]={1,-1,1,-1,1,-1,0,0},dky[8]={1,-1,-1,1,0,0,1,-1};
    int dbx[4]={1,-1,1,-1},dby[4]={1,-1,-1,1};
    int dnx[8]={1,-1,1,-1,2,-2,2,-2},dny[8]={2,-2,-2,2,1,-1,-1,1};
    bool test(int x,int y)
    {
        for(int i=0;i<8;i++){
            int nx=x+dkx[i];
            int ny=y+dky[i];
            if(nx<0||nx>=8)continue;
            if(ny<0||ny>=8)continue;
            if(mp[nx][ny]==1)return true;
        }
        for(int i=0;i<4;i++){
            for(int j=0;j<8;j++){
                int nx=x+dbx[i]*(j+1);
                int ny=y+dby[i]*(j+1);
                if(nx<0||nx>=8)continue;
                if(ny<0||ny>=8)continue;
                if(mp[nx][ny]==2)return true;
                if(mp[nx][ny])break;
            }
        }
        for(int i=0;i<8;i++){
            int nx=x+dnx[i];
            int ny=y+dny[i];
            if(nx<0||nx>=8)continue;
            if(ny<0||ny>=8)continue;
            if(mp[nx][ny]==3)return true;
        }
        return false;
    }
    bool check()
    {
        if(!test(bking.first,bking.second))
            return 0;
        for(int i=0;i<8;i++){
            int nx=bking.first+dkx[i];
            int ny=bking.second+dky[i];
            if(nx<0||nx>=8)continue;
            if(ny<0||ny>=8)continue;
            if(!test(nx,ny))
                return 0;
        }
        return 1;
    }
    int main()
    {
        string s;
        cin>>s;wking=pos(s),mp[wking.first][wking.second]=1;
        cin>>s;bishop=pos(s),mp[bishop.first][bishop.second]=2;
        cin>>s;knight=pos(s),mp[knight.first][knight.second]=3;
        cin>>s;bking=pos(s),mp[bking.first][bking.second]=4;
        for(int i=0;i<8;i++){
            int nx=knight.first+dnx[i];
            int ny=knight.second+dny[i];
            if(nx<0||nx>=8)continue;
            if(ny<0||ny>=8)continue;
            if(mp[nx][ny])continue;
            mp[nx][ny]=3;
            mp[knight.first][knight.second]=0;
            knight=make_pair(nx,ny);
            if(check()){
                printf("N%c%c
    ",'a'+nx,'1'+ny);
                return 0;
            }
            mp[nx][ny]=0;
            knight=make_pair(nx-dnx[i],ny-dny[i]);
            mp[knight.first][knight.second]=3;
        }
        for(int i=0;i<8;i++){
            int nx=wking.first+dkx[i];
            int ny=wking.second+dky[i];
            if(nx<0||nx>=8)continue;
            if(ny<0||ny>=8)continue;
            if(mp[nx][ny])continue;
            int ff=0;
            for(int j=0;j<8;j++){
                int nnx=nx+dkx[j];
                int nny=ny+dky[j];
                if(nnx<0||nnx>=8)continue;
                if(nny<0||nny>=8)continue;
                if(mp[nnx][nny]==4)ff=1;
            }
            if(ff)continue;
            mp[nx][ny]=1;
            mp[wking.first][wking.second]=0;
            wking=make_pair(nx,ny);
            if(check()){
                printf("K%c%c
    ",'a'+nx,'1'+ny);
                return 0;
            }
            mp[nx][ny]=0;
            wking=make_pair(nx-dkx[i],ny-dky[i]);
            mp[wking.first][wking.second]=1;
    
        }
    
        for(int i=0;i<4;i++){
            for(int j=0;j<8;j++){
                int nx=bishop.first+dbx[i]*(j+1);
                int ny=bishop.second+dby[i]*(j+1);
                if(nx<0||nx>=8)continue;
                if(ny<0||ny>=8)continue;
                if(mp[nx][ny])break;
                mp[nx][ny]=2;
                mp[bishop.first][bishop.second]=0;
                bishop=make_pair(nx,ny);
                if(check()){
                    printf("B%c%c
    ",'a'+nx,'1'+ny);
                    return 0;
                }
                mp[nx][ny]=0;
                bishop=make_pair(nx-dbx[i]*(j+1),ny-dby[i]*(j+1));
                mp[bishop.first][bishop.second]=2;
    
            }
        }
        cout<<"impossible"<<endl;
    }
    

    Problem H. Kids’ Play

    题意

    给你一个有向图图,n点n边,点的度数小于等于2,每个点都在环上

    然后Q次查询,每次查询从一个点开始,问这个点跑k步之后在哪个点上。

    题解

    处理出每个环,然后对于每一个点都倍增处理这个点走2^k步之后在哪儿。

    然后暴力去搞一搞就好了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+7;
    vector<int> E[maxn],cir[maxn];
    int vis[maxn],p[maxn][2],n,m,cnt,step[maxn][20],be[maxn],two[maxn];
    void dfs(int x)
    {
        if(vis[x])return;
        vis[x]=1;
        cir[cnt].push_back(x);
        be[x]=cnt;
        for(int i=0;i<E[x].size();i++){
            step[x][0]=E[x][i];
            dfs(E[x][i]);
        }
    }
    int main()
    {
        two[0]=1;
        for(int i=1;i<20;i++)
            two[i]=two[i-1]*2;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            p[a][0]=i,p[b][1]=i;
            step[i][0]=i;
        }
        for(int i=1;i<=n;i++)
            E[p[i][1]].push_back(p[i][0]);
        for(int i=1;i<=n;i++)
            if(!vis[i])
            {
                cnt++;
                dfs(i);
            }
        for(int j=1;j<20;j++)
            for(int i=1;i<=n;i++)
                step[i][j]=step[step[i][j-1]][j-1];
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            b%=cir[be[a]].size();
            int now = a;
            for(int j=19;j>=0;j--)
            {
                if(b>=two[j])
                {
                    now=step[now][j];
                    b-=two[j];
                }
            }
            cout<<now<<endl;
        }
    }
    

    Problem I. Odd Factor (64 MB ML!)

    题意

    给你一个无向图,让你删除一些边,使得每个点的度数都是奇数

    题解

    先找一棵树出来,然后自下而上,如果这个点度数为偶数,就删除这个点与根相连的边就好了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6+7;
    vector<int> E[maxn];
    vector<int> id[maxn];
    vector<int>ans1,ans2,ans3;
    int vis[maxn];
    int V[maxn],d[maxn],fa[maxn],p[maxn];
    int n,m,flag=0;
    void dfs(int x)
    {
        vis[x]=1;
        for(int i=0;i<E[x].size();i++){
            if(vis[E[x][i]])continue;
            d[E[x][i]]++;
            d[x]++;
            ans1.push_back(x);
            ans2.push_back(E[x][i]);
            ans3.push_back(1);
            p[E[x][i]]=ans1.size()-1;
            dfs(E[x][i]);
        }
        if(p[x]==-1){
            if(d[x]%2==0)flag=1;
        }else{
            if(d[x]%2==0){
                d[x]--;
                d[ans1[p[x]]]--;
                ans3[p[x]]=0;
            }
        }
    }
    int main()
    {
        memset(p,-1,sizeof(p));
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            E[a].push_back(b);
            E[b].push_back(a);
            id[a].push_back(i);
            id[b].push_back(i);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])dfs(i);
        if(flag){
            cout<<"-1"<<endl;
            return 0;
        }
        int tmp = 0;
        for(int i=0;i<ans1.size();i++)
            if(ans3[i])tmp++;
        cout<<tmp<<endl;
        for(int i=0;i<ans1.size();i++)
            if(ans3[i]==1)
                cout<<ans1[i]<<" "<<ans2[i]<<endl;
        return 0;
    }
    

    Problem K. Average Speed

    题意

    给你每个时间段汽车的速度,多次查询汽车在某个时间一共跑了多远

    题解

    签到题,水题

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    string s;
    double gettime(string s)
    {
        double h = (s[0]-'0')*10+s[1]-'0';
        double m = (s[3]-'0')*10+s[4]-'0';
        double ss = (s[6]-'0')*10+s[7]-'0';
        return h+m/60.0+ss/3600.0;
    }
    int main()
    {
        double now = 0;
        double lasttime = 0;
        double lastspeed = 0;
        while(getline(cin,s))
        {
            if(s.size()>8){
                double time = gettime(s);
                now+=(time-lasttime)*lastspeed;
                lastspeed=0;
                for(int i=9;i<s.size();i++)
                    lastspeed=lastspeed*10+s[i]-'0';
                lasttime=time;
            }
            else{
                double time = gettime(s);
                cout<<s<<" ";
                printf("%.2f km
    ",(time-lasttime)*lastspeed+now);
            }
        }
    }
    

    Problem L. Subway

    题意

    给你一个二维平面,上面有地铁,地铁的速度和人的速度给你

    现在让你从起点到家,问你怎么走最快。

    题解

    把直接走路和地铁的边都扔进邻接矩阵里面,然后去跑floyd就好了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    double x1,y1,x2,y2;
    double lx,ly,nx,ny;
    int cnt=0;
    double X[250],Y[250];
    double len[250];
    double dp[250][250];
    double dis(double x,double y,double xx,double yy){
        return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
    }
    int main()
    {
        for(int i=0;i<250;i++)
            for(int j=0;j<250;j++)
                if(i==j)dp[i][j]=0;
                else dp[i][j]=1e9;
        cin>>x1>>y1>>x2>>y2;
        cnt++;X[0]=x1,Y[0]=y1;
        while(cin>>nx>>ny){
            int st=cnt;
            len[cnt]=0;
            X[cnt]=nx,Y[cnt]=ny;
            for(int i=0;i<cnt;i++)
            {
                dp[cnt][i]=min(dp[cnt][i],dis(nx,ny,X[i],Y[i])/1000.0*6);
                dp[i][cnt]=min(dp[i][cnt],dis(nx,ny,X[i],Y[i])/1000.0*6);
            }
            cnt++;
            while(cin>>lx>>ly){
                if(lx==-1&&ly==-1)break;
                swap(lx,nx);
                swap(ly,ny);
                len[cnt]=dis(lx,ly,nx,ny)+len[cnt-1];
                X[cnt]=nx,Y[cnt]=ny;
                for(int i=0;i<cnt;i++)
                {
                    dp[cnt][i]=min(dp[cnt][i],dis(nx,ny,X[i],Y[i])/1000.0*6);
                    dp[i][cnt]=min(dp[i][cnt],dis(nx,ny,X[i],Y[i])/1000.0*6);
                }
                for(int i=st;i<cnt;i++)
                {
                    dp[cnt][i]=min(dp[cnt][i],(len[cnt]-len[i])/4000.0*6);
                    dp[i][cnt]=min(dp[i][cnt],(len[cnt]-len[i])/4000.0*6);
                }
                cnt++;
            }
        }
        X[cnt]=x2,Y[cnt]=y2;
        for(int i=0;i<=cnt;i++){
            for(int j=0;j<=cnt;j++){
                if(i==j)dp[i][j]=0;
                else dp[i][j]=min(dp[i][j],dis(X[i],Y[i],X[j],Y[j])/1000.0*6);
            }
        }
        for(int k=0;k<=cnt;k++){
            for(int j=0;j<=cnt;j++){
                for(int i=0;i<=cnt;i++)
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
            }
        }
        printf("%.0f
    ",dp[0][cnt]);
    }
    

    Problem M. A multiplication game

    题意

    一开始数是1,两人在玩博弈论,该一个人的时候,就让他乘上2~9中的一个数,如果这个数大于等于p就胜利。

    题解

    直接dfs搜吧,感觉上状态很小的样子

    代码

    #include<bits/stdc++.h>
    using namespace std;
    long long n;
    map<long long,int>H;
    int dfs(long long o){
        if(H[o])return H[o]-1;
        if(o>=n)return 1;
        int flag = 1;
        for(int i=2;i<=9;i++)
            if(dfs(o*1ll*i))
                flag=0;
        H[o]=flag+1;
        return flag;
    }
    int main()
    {
        while(cin>>n)
        {
            if(n==1){
                cout<<"Stan wins."<<endl;
                continue;
            }
            H.clear();
            int o=dfs(1);
            if(o==0)cout<<"Stan wins."<<endl;
            else cout<<"Ollie wins."<<endl;
        }
    }
  • 相关阅读:
    hdu 5387 Clock (模拟)
    CodeForces 300B Coach (并查集)
    hdu 3342 Legal or Not(拓扑排序)
    hdu 3853 LOOPS(概率DP)
    hdu 3076 ssworld VS DDD(概率dp)
    csu 1120 病毒(LICS 最长公共上升子序列)
    csu 1110 RMQ with Shifts (线段树单点更新)
    poj 1458 Common Subsequence(最大公共子序列)
    poj 2456 Aggressive cows (二分)
    HDU 1869 六度分离(floyd)
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5968005.html
Copyright © 2011-2022 走看看