• [CPSX] [题解] 1009


    前言

    题目较水,恭喜 lcj 神仙 AK 本场比赛。

    T1

    原题:CF1131A Sea Battle

    稍微思索一番,不难推出公式为 $$ (max(w_1,w_2)+1) imes 2+(h_1+h_2+1) imes 2 $$ (变形很多,这里给出一种)。

    Code
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    using namespace std;
    #define ull unsigned ll
    #define INF 0x3f3f3f3f
    #define reg register
    #define ll long long
    #define GC getchar()
    #define R read()
    ll read(){
        char c=GC; ll s=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-f;c=GC;}
        while(c>='0'&&c<='9'){s=s*10+c-'0';c=GC;}
        return s*f;
    }
    int main(){
        int a(R), b(R), c(R), d(R);
        printf("%d",(max(a,c)+1)*2+(b+d+1)*2);
        return 0;
    }
    

    T2

    原题:P1429 平面最近点对(加强版)

    二分+递归。

    首先排序,然后不断从中间劈开,从最小的单位开始回溯,回溯时处理两点分别在两段的情况即可(注意优化)。

    Code
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    using namespace std;
    #define reint register int
    #define ull unsigned ll
    #define INF 0x3f3f3f3f
    #define ll long long
    #define GC getchar()
    #define MAXN 200005
    #define R read()
    ll read(){
        ll s=0,f=1;
        char c=GC;
        while(c<'0'||c>'9'){if(c=='-')f=-f;c=GC;}
        while(c>='0'&&c<='9'){s=s*10+c-'0';c=GC;}
        return s*f;
    }
    typedef double db;
    struct node {
        db x,y;
        bool operator < (const node &Get) const {
        	if(y!=Get.y) return y<Get.y; return x<Get.x;
    	}
    } p[MAXN];
    struct nodeX {
    	db x,y; int i;
        bool operator < (const nodeX &Get) const {
        	if(x!=Get.x) return x<Get.x; return y<Get.y;
    	}
    } p1[MAXN];
    int n;
    db Len(db _,db _1,db _2,db _3) { return sqrt((_-_2)*(_-_2)+(_1-_3)*(_1-_3)); }
    db dfs(int LfI,int RtI) {
    	if(LfI==RtI) return INF;
    	if(LfI==RtI-1) return Len(p[LfI].x,p[LfI].y,p[RtI].x,p[RtI].y);
    	int mid=(LfI+RtI)/2;
    	db ans=min(dfs(LfI,mid),dfs(mid+1,RtI));
    	int pn=0;
    	for(int i=LfI;i<=RtI;++i){
    		if(!(fabs(p[i].y-p[mid].y)>ans)){
    			p1[++pn].x=p[i].x;
    			p1[pn].y=p[i].y;
    		}
    	}
    	sort(p1+1,p1+pn+1);
    	for(int i=1;i<=pn;++i)
    		for(int j=i+1;j<=pn&&!(p1[j].x-p1[i].x>ans);++j)
    			ans=min(ans,Len(p1[i].x,p1[i].y,p1[j].x,p1[j].y));
    	return ans;
    }
    int main(){
        cin>>n; for(int i=1;i<=n;++i) cin>>p[i].x>>p[i].y;
        sort(p+1,p+n+1); return !printf("%.4lf",dfs(1,n));
    }
    

    T3

    原题:P3916 图的遍历

    不难发现,若 1 能够到 4 ,则反向建边 4 一定可以到 1

    稍加推理知,反向建边后遍历点 n1,看它们能到达哪里,能到达的地方若是之前没有被到达过则那个地方能到达的最大的点就是它。

    Code
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <list>
    using namespace std;
    #define R read()
    #define GC getchar()
    #define ll long long
    #define ull unsigned long long
    #define INF 0x7fffffff
    #define LLINF 0x7fffffffffffffff
    ll read(){
        ll s=0,f=1;
        char c=GC;
        while(c<'0'||c>'9'){if(c=='-')f=-f;c=GC;}
        while(c>='0'&&c<='9'){s=s*10+c-'0';c=GC;}
        return s*f;
    }
    int n,m;
    int u,v;
    int ans[100010];
    vector<int> e[100010];
    void dfs(int now,int id){
        if(ans[now]){
            return ;
        }
        ans[now]=id;
        for(int i=0;i<e[now].size();++i){
            dfs(e[now][i],id);
        }
    }
    int main(){
        n=R;m=R;
        for(int i=1;i<=m;++i){
            u=R;v=R;
            e[v].push_back(u);
        }
        for(int i=n;i>=1;--i){
            dfs(i,i);
        }
        for(int i=1;i<=n;++i){
            printf("%d ",ans[i]);
        }
        return 0;
    }
    

    T4

    原题:P1363 幻象迷宫

    裸暴力。

    稍加思索排除几种不正确算法,最后选出正解(笑)。

    若一个点能够被不重复的经过两次,则有解。

    因为是由相同的阵法组成,所以若是经过了另一个阵法的能与初始阵法相对应的点,则称不重复的经过两次

    正确性待大家证明(笑)。

    最后注意坐标问题,因为取模所以会出现 0 哦。

    Code
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    using namespace std;
    #define ull unsigned ll
    #define INF 0x3f3f3f3f
    #define reg register
    #define ll long long
    #define GC getchar()
    #define R read()
    ll read(){
        char c=GC; ll s=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-f;c=GC;}
        while(c>='0'&&c<='9'){s=s*10+c-'0';c=GC;}
        return s*f;
    }
    int n,m,ax,ay; char mp[1505][1505];
    int flag,vis[1505][1505][3];
    int dx[7]={0,-1,1,0,0};
    int dy[7]={0,0,0,-1,1};
    void dfs(int x,int y,int modx,int mody){
        if((vis[modx][mody][0]!=x||vis[modx][mody][1]!=y)&&vis[modx][mody][2])
            { flag=1; return ; }
        if(vis[modx][mody][0]==x&&vis[modx][mody][1]==y&&vis[modx][mody][2])
            return ;
        vis[modx][mody][0]=x;
        vis[modx][mody][1]=y;
        vis[modx][mody][2]=1;
        for(int i=1;i<=4;++i){
            int tx=x+dx[i], ty=y+dy[i];
            int modtx=(modx+dx[i]+n)%n, modty=(mody+dy[i]+m)%m;
            if(mp[modtx][modty]!='#')
                dfs(tx,ty,modtx,modty);
        }
    }
    int main(){
        while(cin>>n>>m){
            memset(vis,0,sizeof(vis)); flag=0;
            for(int i=0;i<n;++i){
                for(int j=0;j<m;++j){
                    cin>>mp[i][j];
                    if(mp[i][j]=='S') ax=i, ay=j;
                }
            }
            dfs(ax,ay,ax,ay);
            if(flag) puts("Yes");
            else puts("No");
        }
        return 0;
    }
    
  • 相关阅读:
    C#引用类型详细剖析(转)
    wcf问题集锦
    Emgu CV 初试
    C#语言使用习惯
    多线程和消息机制
    ArrayAdapter
    SimpleAdapter
    删除对话框
    HTML制作个人简历
    冒泡排序
  • 原文地址:https://www.cnblogs.com/FUXyao/p/14323874.html
Copyright © 2020-2023  润新知