省赛选拔赛——个人赛第二场

来源:互联网 发布:淘宝怎么解封永久封号 编辑:程序博客网 时间:2024/05/16 13:49

Rank 5,AC5道,全部1Y。
开场读错了A题,打了就交,直接WA。后来一路跟题,出了几个水题。刷完水题之后,卡在一道BFS上,浪费了不少时间,导致两道简单DP出得特别晚。后来卡D题的BFS,没有想到进行预处理,也一直没有AC。
C:POJ 3668
出了H之后,继续跟榜,25分钟1Y。
给出n个点,求有多少个不平行的直线。枚举每两个点的连线,用set储存斜率,判断是否有斜率不存在的情况后,求和输出。

#include<iostream>#include<set>using namespace std;const int maxn=200;struct point{    int x,y;    point(int x=0,int y=0):x(x),y(y){}}a[maxn];set<double> k;int main(){    int n;    while(cin>>n){        k.clear();        bool flag=false;        for(int i=0;i<n;++i)            cin>>a[i].x>>a[i].y;        for(int i=0;i<n;++i)            for(int j=i+1;j<n;++j)                if(a[i].x==a[j].x) flag=true;                else k.insert((double)(a[i].y-a[j].y)/(a[i].x-a[j].x));        cout<<k.size()+flag<<endl;    }    return 0;}

D:POJ 3669
m颗流星,每颗毁坏目标点和目标点周围四个点,给出流星的落点和时间,求从原点走到安全地方的最短时间。首先进行预处理,记录每个点被毁坏的时间,然后BFS求解。
比赛时没有想到预处理的方式,WA好几次最后也没出,赛后补的这道题。

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;typedef pair<int,int> pii;const int maxn=310;const int inf=0x3f3f3f3f;const int go[4][2]={{1,0},{-1,0},{0,1},{0,-1}};int m,g[maxn][maxn],vis[maxn][maxn];queue<pii> q;void boom(int x,int y,int t){    g[x][y]=min(g[x][y],t);    for(int i=0;i<4;++i){        int a=x+go[i][0],b=y+go[i][1];        if(a>=0&&a<maxn&&b>=0&&b<maxn)            g[a][b]=min(g[a][b],t);    }    return;}int main(){    while(~scanf("%d",&m)){        while(!q.empty()) q.pop();        memset(g,0x3f,sizeof(g));        memset(vis,-1,sizeof(vis));        for(int i=0;i<m;++i){            int x,y,t;            scanf("%d%d%d",&x,&y,&t);            boom(x,y,t);        }        pii tmp=make_pair(0,0);        q.push(tmp);        vis[0][0]=0;        while(!q.empty()){            tmp=q.front();            q.pop();            if(g[tmp.first][tmp.second]==inf) break;            for(int i=0;i<4;++i){                int a=tmp.first+go[i][0],b=tmp.second+go[i][1];                if(vis[a][b]!=-1||g[a][b]<=vis[tmp.first][tmp.second]+1) continue;                if(a>=0&&a<maxn&&b>=0&&b<maxn){                    vis[a][b]=vis[tmp.first][tmp.second]+1;                    q.push(make_pair(a,b));                }            }        }        if(g[tmp.first][tmp.second]==inf) printf("%d\n",vis[tmp.first][tmp.second]);        else printf("-1\n");    }    return 0;}

E:POJ 3670
跟F题很像的一道题,把F的代码粘贴两次,之后修改下就过了,145分钟1Y。

#include<iostream>#include<algorithm>using namespace std;const int maxn=30010;int a[maxn];int main(){    ios::sync_with_stdio(false);    int n;    while(cin>>n){        int ans=0,ans1=maxn,ans2=maxn,one=0,n_one=0,two=0,three=0;        for(int i=0;i<n;++i){            cin>>a[i];            if(a[i]==1) ++one;            //else ++n_one;        }        int pos=0;        for(int i=0;i<n;++i){            if(a[i]==1) --one;            if(ans1>one+n_one) pos=i;            ans1=min(one+n_one,ans1);            if(a[i]!=1) ++n_one;        }        for(int i=pos;i<n;++i)            if(a[i]==2) ++two;        for(int i=pos;i<n;++i){            if(a[i]==2) --two;            ans2=min(two+three,ans2);            if(a[i]==3) ++three;        }        ans=ans1+ans2;        ans1=maxn,ans2=maxn,one=0,n_one=0,two=0,three=0;        for(int i=0;i<n/2;++i)            swap(a[i],a[n-1-i]);        for(int i=0;i<n;++i)            if(a[i]==1) ++one;            //else ++n_one;        pos=0;        for(int i=0;i<n;++i){            if(a[i]==1) --one;            if(ans1>one+n_one) pos=i;            ans1=min(one+n_one,ans1);            if(a[i]!=1) ++n_one;        }        for(int i=pos;i<n;++i)            if(a[i]==2) ++two;        for(int i=pos;i<n;++i){            if(a[i]==2) --two;            ans2=min(two+three,ans2);            if(a[i]==3) ++three;        }        cout<<min(ans1+ans2,ans)<<endl;    }    return 0;}

F:POJ 3671
D题卡了好久,一直WA,在119分钟最后一次D题提交WA之后,去做这道,130分钟1Y。
给出一个有1、2组成的序列,求最少改动几个数字使得前面是1,后面是2。
简单DP,没写状态转移方程,直接遍历求每个位置改动的最小值输出。

#include<iostream>#include<algorithm>using namespace std;const int maxn=30010;int a[maxn];int main(){    ios::sync_with_stdio(false);    int n;    while(cin>>n){        int ans=maxn,one=0,two=0;        for(int i=0;i<n;++i){            cin>>a[i];            if(a[i]==1) ++one;        }        for(int i=0;i<n;++i){            if(a[i]==1) --one;            ans=min(one+two,ans);            if(a[i]==2) ++two;        }        cout<<ans<<endl;    }    return 0;}

G:POJ 3672
AC了C题之后,看到有出这个的,又跟了。30分钟1Y。
输入u、f、d表示上坡、平地、下坡,求给定时间的最长路程。

#include<string>#include<algorithm>#include<iostream>#include<set>using namespace std;const int maxn=200;int main(){    int m,t,u,f,d;    while(cin>>m){        int cnt=0;        cin>>t>>u>>f>>d;        for(int i=0;i<t;++i){            cin.get();            if(cin.get()=='f') m-=2*f;            else m-=(u+d);            if(m<0) break;            ++cnt;        }        cout<<cnt<<endl;    }    return 0;}

H:POJ 3673
简单求和,A题WA之后,看榜上有人AC之后马上跟的,12分钟1Y。

#include<string>#include<algorithm>#include<iostream>using namespace std;int main(){    string s1,s2;    while(cin>>s1>>s2){        long long sum=0;        for(int i=0;i<s1.size();++i)            for(int j=0;j<s2.size();++j)                sum+=(s1[i]-'0')*(s2[j]-'0');        cout<<sum<<endl;    }    return 0;}
0 0
原创粉丝点击