zoukankan      html  css  js  c++  java
  • 2018.8.6提高B组模拟考试

    爆零了...爽到

    T1 题意简述:jzoj3470

    Description

    给定一个n个点m条边的有向图,有k个标记点,要求从规定的起点按任意顺序经过所有标记点到达规定的终点,问最短的距离是多少。

    Input

    第一行5个整数n、m、k、s、t,表示点个数、边条数、标记点个数、起点编号、终点编号。
    接下来m行每行3个整数x、y、z,表示有一条从x到y的长为z的有向边。
    接下来k行每行一个整数表示标记点编号。

    Output

    输出一个整数,表示最短距离,若没有方案可行输出-1。

    Data Constraint

    20%的数据n<=10。
    50%的数据n<=1000。
    另有20%的数据k=0。
    100%的数据n<=50000,m<=100000,0<=k<=10,1<=z<=5000。

       解题思路:k遍dijkstra或SPFA+爆搜即可。由于k只有10,因此比状压dp还要快些。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define INF 0x3f3f3f3f3f3f3f3f
    #define ll long long
    using namespace std;
    ll n,m,k,s,t,cnt,ans=INF,head[50001];
    ll mp[50001],pnt[11],len[20][20];
    ll dis[50001],vis[50001];
    struct uio{
        ll nxt,to,val;
    }edge[100001];
    void add(ll x,ll y,ll z)
    {
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;
        edge[cnt].val=z;
        head[x]=cnt;
    }
    void spfa(ll x)
    {
        memset(dis,0x3f,sizeof(dis));
        queue<ll> que;
        while(!que.empty()) que.pop();
        dis[x]=0;
        vis[x]=1;
        que.push(x);
        while(!que.empty())
        {
            ll now=que.front();
            que.pop();
            vis[now]=0;
            for(ll i=head[now];i;i=edge[i].nxt)
            {
                ll y=edge[i].to;
                if(dis[y]>dis[now]+edge[i].val)
                {
                    dis[y]=dis[now]+edge[i].val;
                    if(!vis[y]) vis[y]=1,que.push(y);
                }
            }
        }
    }
    void dfs(ll x,ll now,ll l)
    {
        if(l>ans) return;
        if(x==k)
        {
            ans=min(ans,l+len[now][k+1]);
            return;
        }
        for(ll i=1;i<=k;i++)
            if(!vis[i]&&i!=now&&len[now][i]!=INF)
                vis[i]=1,dfs(x+1,i,l+len[now][i]),vis[i]=0;
    }
    int main()
    {
        scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&s,&t);
        for(ll i=1;i<=m;i++)
        {
            ll u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            add(u,v,w);
        }
        for(ll i=1;i<=k;i++)
        {
            scanf("%lld",&pnt[i]);
            mp[pnt[i]]=++mp[0];
        }
        spfa(s);
        for(ll i=1;i<=k;i++)
            len[0][mp[pnt[i]]]=dis[pnt[i]];
        if(!k)
        {
            if(dis[t]==INF) printf("-1
    ");
            else printf("%lld
    ",dis[t]);
            return 0;
        }
        for(ll i=1;i<=k;i++)
        {
            spfa(pnt[i]);
            len[mp[pnt[i]]][k+1]=dis[t];
            for(ll j=1;j<=k;j++)
                len[mp[pnt[i]]][mp[pnt[j]]]=dis[pnt[j]];
        }
        dfs(0,0,0);
        if(ans==INF) printf("-1
    ");
        else printf("%lld
    ",ans);
        return 0;
    }

    T2 题意简述:jzoj3487

    Description

    万老师听说某大国很流行穿越,于是他就想写一个关于穿越的剧本。
    闲话休提。话说老师穿越到了某一个剑与魔法的大陆。因为如此这般,所以老师从维娜艾那里得到了预言。老师一共被告知了若干件按顺序结算的事件。这些事件分为两类:战役事件(CASE)、穿越回去事件(END)。战役事件可以选择是否参加,参加了之后会获得一定的金钱。每个END事件发生需要至少参加一定数量的战役事件。特别的是,END事件如果满足要求就会强制发生。老师希望在大陆玩个够,所以他要求只有最后一个END事件会发生。老师希望获得最多的金钱,所以求助于你。   

    Input

    第一行一个数N,表示输入文件有多少行。
    接下来每一行用空格隔开一个字符和一个整数。字符为“c”表示战役事件,接下来的整数表示这次涨RP顺带有多少钱;字符为“e”表示穿越回去事件,接下来的整数代表至少要涨多少RP。最后一个事件保证是END事件。   

    Output

    第一行一个整数,最多金钱数目。
    若不可能则输出-1。

    Data Constraint

    30%的数据满足 N<=20
    60%的数据满足 N<=1,000
    100%的数据满足 N<=200,000
    每次涨RP事件赏金不超过10,000
    穿越事件的要求不超过200,000   

       解题思路:小根堆维护所有事件即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f3f3f3f3f
    #define ll long long
    using namespace std;
    int n,ans;
    priority_queue<int,vector<int>,greater<int> > que;
    int main()
    {
        scanf("%d
    ",&n);
        for(int i=1;i<n;i++)
        {
            char c;int u;
            scanf("%c %d
    ",&c,&u);
            if(c=='c') que.push(u);
            else while(que.size()>=u) que.pop();
        }
        char c;int u;
        scanf("%c %d",&c,&u);
        if(que.size()<u) {printf("-1
    ");return 0;}
        while(!que.empty())
            ans+=que.top(),que.pop();
        printf("%d
    ",ans);
        return 0;
    }

    T3 题意简述:jzoj3493

    Description

    平面上有n个点,求出用这些点可以构成的三角形数。

    Input

    第一行一个整数n。
    接下来n行,每行两个整数,表示点的坐标。

    Output

    输出仅一个整数,表示所求答案。

    Data Constraint

    对于50%的数据,n<=300。
    对于100%的数据,n<=3000,坐标的绝对值不超过10^4,保证没有重合的点。

       解题思路:枚举每个点,把其它点与这个点的斜率计算出来,将斜率相同的合并,计算组合数,用总方

                 案数减去计算出的组合数即可。

                 如何去重?只需在第二重循环时只枚举i+1~n的点且只把包含i的不合法情况去除即可。

                 考虑以下例子:编号为1 2 3 4的点排成一条直线。

                 枚举到1时,只把包含1的不合法情况去除。在本例子中,即去除(1,2,3)(1,2,4)(1,3,4)。

                 枚举到2时,只把包含2的不合法情况去除。在本例子中,即去除(2,3,4)。

                 以此类推,只需计算C(n,3)-∑(i=1~n)∑(j=i+1~n)C(k,2) 其中k表示相同斜率的数量。

                 感谢ErkkiErkko大佬和Menteur_Hxy大佬!!!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define INF 0x3f3f3f3f3f3f3f3f
    #define ll long long
    using namespace std;
    ll n,cnt,ans;
    double k[10001],a[10001],b[10001];
    int main()
    {
        freopen("triangle.in","r",stdin);
        freopen("triangle.out","w",stdout);
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)
            scanf("%lf%lf",&a[i],&b[i]);
        for(ll i=1;i<=n;i++)
        {
            cnt=0,memset(k,0xc0,sizeof(k));
            for(ll j=i+1;j<=n;j++)
                if(a[i]==a[j]) k[++cnt]=INF;
                else k[++cnt]=(b[j]-b[i])/(a[j]-a[i]);
            sort(k+1,k+1+cnt);
            ll tmp=1;
            for(ll j=2;j<=cnt+1;j++)
                if(k[j]==k[j-1]) tmp++;
                else ans+=tmp*(tmp-1)/2,tmp=1;
        }
        printf("%lld",n*(n-1)*(n-2)/6-ans);
        return 0;
    }
  • 相关阅读:
    Node.js安装及环境配置(windows)
    table
    检测浏览器
    ickeck插件
    全国三级联动
    css3-calc用法
    jQuery Portamento 滑动定位
    canvas版《俄罗斯方块》
    canvas入门级小游戏《开关灯》思路讲解
    css3 matrix 2D矩阵和canvas transform 2D矩阵
  • 原文地址:https://www.cnblogs.com/water-radish/p/9431310.html
Copyright © 2011-2022 走看看