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

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;
}

你可能感兴趣的:(ACM)