zoukankan      html  css  js  c++  java
  • NOI 2011

    [NOI2011]兔农

     暴力O(n)递推就有75。。。记下模k的结果和模g的结果,遇到模k等于1两个都减一。

    注意滚动。

    CODE:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=1e7+10;
    long long f[5],g[5];
    long long n,k,mod; 
    
    int main()
    {
        scanf("%lld%lld%lld",&n,&k,&mod);
        f[1]=f[2]=1;
        g[1]=g[2]=1;
        for(long long i=3;i<=n;i++)
        {
            f[3]=(f[1]+f[2])%k;
            g[3]=(g[1]+g[2])%mod;
            if(f[3]%k==1) g[3]--,f[3]=0;
            g[3]=(g[3]+mod)%mod;
            g[1]=g[2],g[2]=g[3];
            f[1]=f[2],f[2]=f[3];
        }
        if(n<3) g[3]=g[1];
        printf("%lld",g[3]%mod);
        return 0;
    }
    View Code

    [NOI2011]智能车比赛

    很精彩的一道题。

    可以发现所有的拐点都在矩形的四个角,有DP:

    这个DP用spfa来转移,只不过在扩展队首的时候,要判断是否能够到达。

    现在就变成了如何在最多O(n)时间内判断两点是否可以直接互相达到。

    对于每个点,扩展的时候,维护一个high,一个low,表示张角的限制,因为已经按照x排过序了,所以通过叉积的计算就可以更新啦。

    注意high只能用矩形的2个上角更新,low同理。

    判断的时候也用叉积。

    CODE:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    const int maxn=9003;
    struct Line
    {
        double x,y;
    }line[maxn],s,t;
    int n,st,vis[maxn];
    double v,dis[maxn];
    
    double DIS(Line a,Line b) 
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    double cross(Line o,Line a,Line b) 
    {
        double x1=a.x-o.x,y1=a.y-o.y;
        double x2=b.x-o.x,y2=b.y-o.y;
        return x1*y2-x2*y1;
    }
    
    bool check(int up,int low,Line a,Line b) 
    {
        return !((up && cross(a,line[up],b)>0) || (low && cross(a,line[low],b)<0));
    }
    
    
    inline void spfa()
    {
        queue<int> q;
        for(int i=st;i<=n;i++) dis[i]=1e9;
        dis[st]=0;
        vis[st]=1;
        q.push(st);
        while(!q.empty())
        {
            int tt=q.front();
            q.pop();
            vis[tt]=0;
            int up=0,low=0;
            for(int i=tt+1;i<=n;i++)
            {
                if(check(up,low,line[tt],line[i]))
                {
                    if(dis[tt]+DIS(line[tt],line[i])<dis[i])
                    {
                        dis[i]=dis[tt]+DIS(line[tt],line[i]);
                        if(!vis[i]) vis[i]=1,q.push(i); 
                    }
                }
                if(((i-1)%4+1) & 1 && (!up || cross(line[tt],line[up],line[i])<=0)) up=i;
                else if(!(((i-1)%4+1)&1) && (!low || cross(line[tt],line[low],line[i])>=0)) low=i;
                if(up && low && cross(line[tt],line[up],line[low])>0) break;
            }    
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&line[i*4-2].x,&line[i*4-2].y,&line[i*4-1].x,&line[i*4-1].y);
            line[i*4-3]=(Line){line[i*4-2].x,line[i*4-1].y};
            line[i*4]=(Line){line[i*4-1].x,line[i*4-2].y};        
        }
        n=n*4;
        scanf("%lf%lf",&s.x,&s.y);
        scanf("%lf%lf",&t.x,&t.y);
        scanf("%lf",&v);
        if(s.x>t.x) swap(s,t);
        for(;n;n--) if(line[n].x<=t.x) break;
        line[++n]=t;
        for(st=1;st<=n;st++) if(line[st].x>=s.x) break;
        line[--st]=s;
        spfa();
        printf("%.10lf",dis[n]/v);
        return 0;
    }
    View Code

    [NOI2011]兔兔与蛋蛋游戏

    搜索75/ 非常精彩的一道题

    以空格为起点将棋盘黑白染色,将空格染成黑色,这样相邻两个点的颜色总是不一样的,等效于在二分图的两侧来回走。

    那么一般的,任意给一个棋局,都可以看成一个已经走过一部分的二分图(不可能走重复的格子,因为是黑白交替走),考虑给定二分图先手是否必胜。

    二者相当于走一个交错路(最后一步一定是先手走),由于最大匹配的交错路可以使得后手无路可走,所以我们开始关注最大匹配。

    如果此图中的最大匹配独一无二,先手必胜;

    不然就有可能被后手引上"歧途",从而无路可走。

    如何判断一个点是否是非必需点?

    • 如果当前点本来就没有匹配的点,显然不在。
    • 如果当前点所匹配的点在删去当前点后,能够继续增广,就说明当前点不一定在最大匹配上,否则一定在。

     好好意会吧。。。

    CODE:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn=50003;
    const int maxm=5e6+10;
    struct point
    {
        int x,y;
        int to,nxt;
    }edge[maxm]; 
    int n,m,k,bx,by,cnt,tot;
    int map[203][203],ban[maxn],match[maxn];
    int vis[maxn],viss[203][203],head[maxn],ans[maxn];
    char ss[maxn];
    int derx[]={0,0,0,1,-1};
    int dery[]={0,1,-1,0,0};
    
    inline void add(int u,int v)
    {
        tot++;
        edge[tot].nxt=head[u];
        edge[tot].to=v;
        head[u]=tot;
    }
    
    inline int iu(int x,int y)
    {
        return (x-1)*m+y;
    }
    
    inline void Bfs()
    {
        queue<point> q;
        memset(viss,0,sizeof(viss));
        q.push((point){bx,by,0,0});
        while(!q.empty())
        {
            point e=q.front();
            q.pop();
            for(int i=1;i<=4;i++)
            {
                int xx=e.x+derx[i],yy=e.y+dery[i];
                if(xx<1 || xx>n || yy<1 || yy>m || !(map[e.x][e.y]^map[xx][yy])) continue;
                add(iu(e.x,e.y),iu(xx,yy));    
                add(iu(xx,yy),iu(e.x,e.y));    
                if(!viss[xx][yy])
                {
                    q.push((point){xx,yy,0,0});
                    viss[xx][yy]=1;
                }
            }
        }
    }
    
    inline bool dfs(int x)
    {
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(vis[v] || ban[v]) continue;
            vis[v]=1;
            if(!match[v] || dfs(match[v]))
            {
                match[v]=x;
                match[x]=v;
                return true;
            }
        }
        return false;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ss+1);
            for(int j=1;j<=m;j++)
            {
                if(ss[j]=='.')
                {
                    bx=i,by=j;
                    map[i][j]=1;
                }
                else if(ss[j]=='X') map[i][j]=1;
                else if(ss[j]=='O') map[i][j]=0;
            }
        }
        Bfs();
        for(int i=1;i<=n*m;i++)
            if(!match[i])
            {
                memset(vis,0,sizeof(vis));
                dfs(i);
            }
        scanf("%d",&k);
        for(int i=1;i<=k;i++)
        {
            int cn=iu(bx,by),a1=0,a2=0;
            ban[cn]=1;
            if(match[cn])
            {
                int op=match[cn];
                match[op]=0; match[cn]=0;
                memset(vis,0,sizeof(vis));
                a1=!dfs(op);
            }
            else a1=0;
            scanf("%d%d",&bx,&by);     
            cn=iu(bx,by);
            ban[cn]=1;
            if(match[cn])
            {
                int op=match[cn];
                match[op]=0; match[cn]=0;
                memset(vis,0,sizeof(vis));
                a2=!dfs(op);
            }
            else a2=0;
            if(a1 && a2) ans[++cnt]=i;
            scanf("%d%d",&bx,&by);
        }
        printf("%d
    ",cnt);
        for(int i=1;i<=cnt;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    View Code

    [NOI2011]道路修建

    一遍dfs就行了,NOIP之前做的题 o_O

    //long long 害死人 
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int maxn=1e6+10;
    struct point
    {
        int to;
        long long w;
        int nxt;
    }edge[maxn<<1];
    int n,tot;
    int head[maxn],S[maxn];
    long long ans=0;
    
    inline void add(int u,int v,long long w)
    {
        tot++;
        edge[tot].to=v;
        edge[tot].nxt=head[u];
        edge[tot].w=w;
        head[u]=tot;
    }
    
    inline void dfs(int x,int fa)
    {
        S[x]=1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v!=fa)
            {
                dfs(v,x);
                ans+=(long long)abs(n-S[v]*2)*edge[i].w;
                S[x]+=S[v];
            }    
        }
    }
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n-1;i++)
        {
            int a,b;
            long long w;
            scanf("%d%d%lld",&a,&b,&w);
            add(a,b,w);
            add(b,a,w);
        }
        dfs(1,0);
        printf("%lld",ans);
        return 0;
    }
    View Code

  • 相关阅读:
    支持向量机SVM知识点概括
    决策树知识点概括
    HDU 3081 Marriage Match II
    HDU 3572 Task Schedule
    HDU 4888 Redraw Beautiful Drawings
    Poj 2728 Desert King
    HDU 3926 Hand in Hand
    HDU 1598 find the most comfortable road
    HDU 4393 Throw nails
    POJ 1486 Sorting Slides
  • 原文地址:https://www.cnblogs.com/linda-fcj/p/9120053.html
Copyright © 2011-2022 走看看