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\n",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\n",'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\n",'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\n",'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\n",(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\n",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;
    }
}
posted @ 2016-10-16 22:25  qscqesze  阅读(792)  评论(0编辑  收藏  举报