1. 程式人生 > >Gym-101673 :East Central North America Regional Contest (ECNA 2017)(寒假自訓第8場)

Gym-101673 :East Central North America Regional Contest (ECNA 2017)(寒假自訓第8場)

oid esp next != amp bstr color 多少 圖片

A .Abstract Art

題意:求多個多邊形的面積並。

思路:模板題。

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double inf=1e200;
const double eps=1e-12;
const double pi=4*atan(1.0);
int dcmp(double x){ return fabs(x)<eps?0:(x<0?-1:1);}
struct point{
    double x,y;
    point(double
a=0,double b=0):x(a),y(b){} }; point operator +(point A,point B) { return point(A.x+B.x,A.y+B.y);} point operator -(point A,point B) { return point(A.x-B.x,A.y-B.y);} point operator *(point A,double p){ return point(A.x*p,A.y*p);} point operator /(point A,double p){ return point(A.x/p,A.y/p);} bool
operator ==(const point& a,const point& b){ return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps; } double dot(point A,point B){ return A.x*B.x+A.y*B.y;} double det(point A,point B){ return A.x*B.y-A.y*B.x;} double det(point O,point A,point B){ return det(A-O,B-O);} double length(point A){ return
sqrt(dot(A,A));} double area(vector<point>p){ double ans=0; int sz=p.size(); for(int i=1;i<sz-1;i++) ans+=det(p[i]-p[0],p[i+1]-p[0]); return ans/2.0; } double seg(point O,point A,point B){ if(dcmp(B.x-A.x)==0) return (O.y-A.y)/(B.y-A.y); return (O.x-A.x)/(B.x-A.x); } vector<point>pp[110]; pair<double,int>s[110*60]; double polyunion(vector<point>*p,int N){ double res=0; for(int i=0;i<N;i++){ int sz=p[i].size(); for(int j=0;j<sz;j++){ int m=0; s[m++]=make_pair(0,0); s[m++]=make_pair(1,0); point a=p[i][j],b=p[i][(j+1)%sz]; for(int k=0;k<N;k++){ if(i!=k){ int sz2=p[k].size(); for(int ii=0;ii<sz2;ii++){ point c=p[k][ii],d=p[k][(ii+1)%sz2]; int c1=dcmp(det(b-a,c-a)); int c2=dcmp(det(b-a,d-a)); if(c1==0&&c2==0){ if(dcmp(dot(b-a,d-c))){ s[m++]=make_pair(seg(c,a,b),1); s[m++]=make_pair(seg(c,a,b),-1); } } else{ double s1=det(d-c,a-c); double s2=det(d-c,b-c); if(c1>=0&&c2<0) s[m++]=make_pair(s1/(s1-s2),1); else if(c1<0&&c2>=0) s[m++]=make_pair(s1/(s1-s2),-1); } } } } sort(s,s+m); double pre=min(max(s[0].first,0.0),1.0),now,sum=0; int cov=s[0].second; for(int j=1;j<m;j++){ now=min(max(s[j].first,0.0),1.0); if(!cov) sum+=now-pre; cov+=s[j].second; pre=now; } res+=det(a,b)*sum; } } return res/2; } int main() { int N,M,i,j; point tp; scanf("%d",&N); for(i=0;i<N;i++){ scanf("%d",&M); for(j=0;j<M;j++){ scanf("%lf%lf",&tp.x,&tp.y); pp[i].push_back(tp); } } double t1=0,t2=polyunion(pp,N); for(i=0;i<N;i++) t1+=area(pp[i]); printf("%f %f\n",-t1,-t2); return 0; }
View Code

B .Craters

題意:給定N個圓,讓你用最小的周長把這些圓包起來,且滿足到圓的最近距離不小於10.

思路:把每個圓的半徑增加10,然後等分1000份,然後求凸包即可。

技術分享圖片
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef long long ll;
const double inf=1e200;
const double eps=1e-6;
const double pi=4*atan(1.0);
int dcmp(double x){ return fabs(x)<eps?0:(x<0?-1:1);}
struct point{
    double x,y;
    point(double a=0,double b=0):x(a),y(b){}
};
point operator +(point A,point B) { return point(A.x+B.x,A.y+B.y);}
point operator -(point A,point B) { return point(A.x-B.x,A.y-B.y);}
point operator *(point A,double p){ return point(A.x*p,A.y*p);}
point operator /(point A,double p){ return point(A.x/p,A.y/p);}
point rotate(point A,double rad){
    return point(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
bool operator ==(const point& a,const point& b) {
     return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double dot(point A,point B){ return A.x*B.x+A.y*B.y;}
double det(point A,point B){ return A.x*B.y-A.y*B.x;}
double det(point O,point A,point B){ return det(A-O,B-O);}
double length(point A){ return sqrt(dot(A,A));}
double angle(point A,point B){ return acos(dot(A,B)/length(A)/length(B));}
double area(vector<point>p){
    double ans=0; int sz=p.size();
    for(int i=1;i<sz-1;i++) ans+=det(p[i]-p[0],p[i+1]-p[0]);
    return ans/2.0;
}
double seg(point O,point A,point B){
    if(dcmp(B.x-A.x)==0) return (O.y-A.y)/(B.y-A.y);
    return (O.x-A.x)/(B.x-A.x);
}
bool cmp(point a,point b){ return a.x==b.x?a.y<b.y:a.x<b.x; }
void convexhull(point *a,int n,point *ch,int &top)
{
    sort(a+1,a+n+1,cmp);
    top=0;
    for(int i=1;i<=n;i++){
        while(top>=2&&det(ch[top-1],ch[top],a[i])<=0) top--;
        ch[++top]=a[i];
    }
    int ttop=top;
    for(int i=n-1;i>=1;i--){
        while(top>ttop&&det(ch[top-1],ch[top],a[i])<=0) top--;
        ch[++top]=a[i];
    }
}
point ch[2000000],p[2000000];
int main()
{
    int N,i,j,tot=0,top; double ans,one=pi/2500,x,y,r;
    scanf("%d",&N);
    for(i=1;i<=N;i++){
        scanf("%lf%lf%lf",&x,&y,&r); r+=10;
        for(j=1;j<=5000;j++){
            tot++; p[tot].x=x+r*cos(one*j); p[tot].y=y+r*sin(one*j);
        }
    }
    convexhull(p,tot,ch,top);
    for(i=1;i<top;i++) ans+=length(ch[i]-ch[i+1]);
    printf("%.10lf\n",ans);
    return 0;
}
View Code

C .DRM Messages

題意:字符串操作模擬。

思路:模擬。

技術分享圖片
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2000010;
char c[maxn];
void solve(int L,int R)
{
    int sum=0;
    rep(i,L,R) sum+=c[i]-A;
    sum%=26;
    rep(i,L,R) c[i]=(c[i]-A+sum+26)%26+A;
}
int main()
{
    int N; scanf("%s",c+1);
    N=strlen(c+1);
    solve(1,N/2);
    solve(N/2+1,N);
    rep(i,1,N/2){
        c[i]=(c[i]-A+(c[i+N/2]-A)+26)%26+A;
    }
    rep(i,1,N/2) putchar(c[i]);
    return 0;
}
View Code

D .Game of Throwns

題意:模擬題。

思路:模擬。

技術分享圖片
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2000010;
int q[maxn],tot;
int read()
{
    int x=0,F=1; char c=getchar();
    while(c!=-&&c!=u&&!(c>=0&&c<=9)) c=getchar();
    if(c==-) F=-1,c=getchar();
    else if(c==u) {
        rep(i,1,3) c=getchar(); return maxn;
    }
    while(c>=0&&c<=9) x=x*10+c-0,c=getchar();
    return F*x;
}
int main()
{
    int N,K,x,P=0; scanf("%d%d",&N,&K);
    rep(i,1,K) {
        x=read();
        if(x==maxn)  {
            x=read();
            tot-=x;
        }
        else q[++tot]=x;
    }
    rep(i,1,tot) P=((P+q[i])%N+N)%N;
    printf("%d\n",P);
    return 0;
}
View Code

E .Is-A? Has-A? Who Knowz-A?

題意:題意可能沒有解釋清楚。N個名字,M個傳遞關系,Q次詢問,反正就是有兩種傳遞關系,is和has,A(has or is)->B; B->C; C->D;像這樣的傳遞關系,假如全部都是is,則A可以推出isD;否則可以推出A has D。N<=500。

思路:因為N<500,直接DFS即可,復雜度O(N^3);註意自己和自己有is關系,但是沒有has關系。

技術分享圖片
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=510;
int dis[maxn][maxn][2],tot;
struct in{
    int x,y,opt;
    in(){}
    in(int xx,int yy,int oo):x(xx),y(yy),opt(oo){}
};
queue<in>q; map<string,int>mp;
map<int,string>F;
void name(string s){
    if(mp.find(s)==mp.end()) {
            mp[s]=++tot; F[tot]=s;
    }
}
void DFS()
{
    while(!q.empty()){
        int x=q.front().x,y=q.front().y,op=q.front().opt; q.pop();
        //cout<<":"<<F[x]<<" "<<F[y]<<" "<<op<<endl;
        dis[x][y][op]=1;
        for(int i=1;i<=tot;i++){
            if(!dis[x][i][0]&&dis[y][i][0]){
                dis[x][i][0]=1; q.push(in(x,i,0));
            }
            if(!dis[x][i][0]&&dis[y][i][1]&&op==0){
                dis[x][i][0]=1; q.push(in(x,i,0));
            }
            if(!dis[x][i][1]&&dis[y][i][1]&&op==1){
                dis[x][i][1]=1; q.push(in(x,i,1));
            }
        }
    }
}
int main()
{
    int N,M,u,v,Ca=0; string A,B,C;
    scanf("%d%d",&N,&M);
    rep(i,1,N){
        cin>>A>>B>>C;
        name(A); name(C);
        if(B[0]==i) q.push(in(mp[A],mp[C],1)),dis[mp[A]][mp[C]][1]=1;
        else q.push(in(mp[A],mp[C],0)),dis[mp[A]][mp[C]][0]=1;
    }
    DFS();
    rep(i,1,M){
        cin>>A>>B>>C;
        printf("Query %d: ",++Ca);
        if(A==C&&B[0]==i) {puts("true"); continue;}
        u=mp[A]; v=mp[C];
        if(B[0]==i) {
            if(dis[u][v][1]) puts("true");
            else puts("false");
        }
        else {
            if(dis[u][v][0]) puts("true");
            else puts("false");
        }
    }
    return 0;
}
View Code

F .Keeping On Track

題意:給定一棵樹,問刪去一個點後,不連通的點最對有多少,在此基礎上加一條邊可以最多讓多少對點對恢復連通。

思路:就是dfs一次,然後看所有兒子和父親之上的連通塊的大小; 第二問取最大的兩個連通塊連通即可。

技術分享圖片
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=20010;
int Laxt[maxn],Next[maxn],To[maxn];
int sz[maxn],q[maxn],cnt,ans,fcy,tot,N;
void add(int u,int v)
{
    Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v;
}
void dfs(int u,int f)
{
    sz[u]=1;
    for(int i=Laxt[u];i;i=Next[i]){
        if(To[i]!=f){
            dfs(To[i],u);
            sz[u]+=sz[To[i]];
        }
    }
    tot=0; q[++tot]=N+1-sz[u];
    for(int i=Laxt[u];i;i=Next[i])
      if(To[i]!=f) q[++tot]=sz[To[i]];
    sort(q+1,q+tot+1);
    int sum=0,tmp=0;
    rep(i,1,tot) sum+=q[i];
    rep(i,1,tot) tmp+=(sum-q[i])*q[i];
    tmp/=2;
    if(tmp>ans) ans=tmp,fcy=q[tot]*q[tot-1];
    else if(tmp==ans) fcy=max(fcy,q[tot]*q[tot-1]);
}
int main()
{
    int u,v;
    scanf("%d",&N);
    rep(i,1,N) {
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    dfs(0,-1);
    printf("%d %d\n",ans,ans-fcy);
    return 0;
}
View Code

G .A Question of Ingestion

題意:一個人開始的飯量是M,如果今天吃飯了,第二天的飯量變為今天的2/3;如果今天不吃,第二天的飯量和昨天飯量一樣(即恢復); 如果連續兩天不吃,則第三天的飯量恢復到M。 現在給出N天的食物量, 問怎麽吃可以遲到最多的食物。

思路:DP即可,dp[i][j]表示第i天的時候是連續第j天吃飯的最大食物量。

技術分享圖片
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=210;
int a[maxn],f[maxn],dp[maxn][maxn],ans;
int main()
{
    int N,M;
    scanf("%d%d",&N,&M); f[1]=M;
    rep(i,1,N) scanf("%d",&a[i]);
    rep(i,2,N) f[i]=f[i-1]*2/3;
    rep(i,1,N){
        rep(j,1,i){
            dp[i][j]=max(dp[i][j],dp[i-1][j-1]+min(f[j],a[i]));
            if(i>1)dp[i][j]=max(dp[i][j],dp[i-2][j]+min(f[j],a[i]));
            if(i>2)dp[i][1]=max(dp[i][1],dp[i-3][j]+min(f[1],a[i]));
        }
    }
    rep(i,1,N) ans=max(ans,dp[N][i]);
    printf("%d\n",ans);
    return 0;
}
View Code

H .Sheba‘s Amoebas

題意:問有幾個連通塊。

思路:DFS或者並查集即可。

技術分享圖片
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=210;
char c[maxn][maxn];
int fa[maxn*maxn],ans,N,M;
int x[8]={1,1,1,-1,-1,-1,0,0};
int y[8]={-1,0,1,-1,0,1,-1,1};
int find(int x){
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
void merge(int u,int v)
{
    int fu=find(u),fv=find(v);
    if(fu!=fv) fa[fu]=fv;
}
int main()
{
    scanf("%d%d",&N,&M);
    rep(i,1,N*M) fa[i]=i;
    rep(i,1,N) scanf("%s",c[i]+1);
    rep(i,1,N)
     rep(j,1,M){
        if(c[i][j]==#){
            rep(k,0,7){
                if(i+x[k]>=1&&i+x[k]<=N&&j+y[k]>=1&&j+y[k]<=M&&c[i+x[k]][j+y[k]]==#){
                    merge((i-1)*M+j,(i+x[k]-1)*M+j+y[k]);
                }
            }
        }
    }
    rep(i,1,N)
     rep(j,1,M){
       if(c[i][j]!=#) continue;
       int t=(i-1)*M+j;
       if(find(t)==t) ans++;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

太累了,後面了兩個題先鴿了

Gym-101673 :East Central North America Regional Contest (ECNA 2017)(寒假自訓第8場)