zoukankan      html  css  js  c++  java
  • 校内模拟赛(20170924)

    四校很丧,但是学长的题目更简单

    lrb学长的题目为什么都要倒着切,不懂QAQ

    ————————————————我是分割线————————————————

    T1:个人卫生综合征

    每天BBS都要从家里经过城市中的一段路到学校刷五三。城市中一共有n个路口和m条双向道路,每条双向道路都连接着两个路口aibi且有一定的时间花费viBBS家编号为1,学校编号为n。今天,BBS由于个人卫生综合征导致他很迟才离开家,他想用膜法改变k条道路的长度使通过其的时间花费vi变为0。现在他问你改变道路长度之后他到学校的最小时间花费是多少?

    输入格式:

    第一行为三个整数n、m、k,接下来的m行每行三个整数ai,bi,vi,分别表示这条路连着的两个路口和通过其所用的时间。

    输出格式:

    一个整数,表示BBS到学校的最小时间花费。

    样例输入

    样例输出

    4 4 1
    1 2 10
    2 4 10
    1 3 1
    3 4 100

    1

    样例解释:

    更新3->4的道路,最短路线为1->3->4,用时为1+0=1。

    数据范围:

    对于100%的数据:1<=n<=10000,1<=m<=50000,1<=k<=201<=vi<=1000000

    ————————————————我是分割线————————————————

    emmm本次考试最丧的一题(但不是最坑的QAQ),但是其实也很好想,我们把整张图复制k份,然后跑dij就好了QAQ

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    #define MN 100005
    using namespace std;
    int head[MN],dis[MN][25],num,n,m,k,x,y,v;
    bool vis[MN][25];
    struct node{
        int num,d;
        friend bool operator<(node a,node b){return a.d>b.d;}
    };
    struct edge{
        int to,next,w;
    }g[MN];
    void ins(int u,int v,int w){g[++num].next=head[u];head[u]=num;g[num].to=v;g[num].w=w;}
    priority_queue<node> q;
    void dij(){
        node now;
        memset(dis,inf,sizeof(dis));
        memset(vis,0,sizeof(vis));dis[1][0]=0;
        q.push((node){1,0});
        while(!q.empty()){
            now=q.top();q.pop();//printf("%d
    ",now);
            int t1=(now.num%n==0?n:now.num%n),t2=now.num/n;vis[t1][t2]=true;
            for(int i=head[t1];i;i=g[i].next){
                if((!vis[g[i].to][t2])&&(dis[g[i].to][t2]>dis[t1][t2]+g[i].w)){
                    dis[g[i].to][t2]=dis[t1][t2]+g[i].w;
                    q.push((node){t2*n+g[i].to,dis[g[i].to][t2]});
                }
                if((!vis[g[i].to][t2+1])&&t2<k&&dis[g[i].to][t2+1]>dis[t1][t2]){
                    dis[g[i].to][t2+1]=dis[t1][t2];
                    q.push((node){(t2+1)*n+g[i].to,dis[g[i].to][t2+1]});
                }
            }
        }
    }
    int main(){
        freopen("school.in","r",stdin);
        freopen("school.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&v),ins(x,y,v),ins(y,x,v);
        dij();
        int ans=inf;
        for(int i=0;i<=k;i++)ans=min(ans,dis[n][i]);
        printf("%d
    ",ans);
        fclose(stdin);
        fclose(stdout);
    }

    ————————————————我是分割线————————————————

    T2:你的四边形已如风中残烛

      LGL有一根长为n的木板。现在他想要把它砍成四段长度为整数的木板来做一个四边形,请问他有多少种不同的砍法?注意:四段长度为1、1、2、1和四段长度为1、2、1、1算两种砍法。

     

    输入格式:

    第一行为一个整数 n,表示木板的长度。

    输出格式:

    一个整数,不同的砍法数量。

    样例输入

    样例输出

    6

    6

    样例解释:

    11221212,1221,2112,2121,2211。

    数据范围:

    对于100%的数据:1<=n<=2500

    ————————————————我是分割线————————————————

    当然,我们可以写正解,不过你可以用一些奇特的技巧通过此题,比如:打表。。。。

    下面贴上打表程序!

    #include<cstdio>
    using namespace std;
    int main(){
        freopen("bll.out","w",stdout);
        for(int n=0;n<=2500;n++){
            long long ans=0;
            for(int i=1;i<=n/4;i++)
                for(int j=i;j<=(n-i)/3;j++)
                    for(int k=j;k<=(n-i-j)/2;k++)if(n-i-j-k<i+j+k){
                        if(i==j&&j==k&&k==n-i-j-k)ans++;
                        else if((i==j&&j==k)||(j==k&&k==n-i-j-k))ans+=4;
                        else if(i==j&&k==n-i-j-k)ans+=6;
                        else if(i==j||k==n-i-j-k||j==k)ans+=12;
                        else ans+=24;
                    }
            printf("%lld,",ans);
        }
    }

    242.9秒出正解,贼快QAQ

    好吧,正解我也说一下,就是枚举最小的和第二小的,然后通过数学方法O(1)统计剩下的两条边的情况。

    #include<cstdio>
    int n,mid,ans=0;
    int main(){
        freopen("quad.in","r",stdin);
        freopen("quad.out","w",stdout);
        scanf("%d",&n); mid=(n+1)/2-1;
        for(int i=1;i<=mid;++i){
            for(int j=1;j<=mid;++j){
                int sum=n-i-j;
                ans+=sum>mid?mid+mid-sum+1:sum-1;
            }
        }
        printf("%d",ans);
        return 0;
    }

    ————————————————我是分割线————————————————

    T3:生命不息刷题不止

     YYH有n道题要做。但是由于他上课做某些事,导致他一题都不会做,只好请LGL代打。LGL为了买自己心爱的坦克,他做第i题要收两笔钱:一笔在YYH叫他做题当天收,另外一笔在叫他做题的第二天收。YYH每天结束的时候都会把剩下的所有钱花光,然后再从父亲LRB处得到m元零花钱用来请LGL做题(也就是说,第一天的时候YYH是没有钱请LGL做题的,每一天用来请LGL做题所用的钱都是前一天LRB给的)。而且,YYH做的题目难度是循序渐进的:就算强如LGL,在做第i题之前也要先把第1到i-1题全部做完。请问YYH将所有题目做完并且把所有钱都付给LGL的最小天数。

    输入格式:

    第一行为两个整数m、n,接下来的n行每一行都有两个数aibi,分别表示LGL做第i题所收的两笔钱。

    输出格式:

    一个整数,表示最小天数。

    样例输入

    样例输出

    100 5
    40 20
    60 20
    30 50
    30 50
    40 40

    6

    样例解释:

    第二天做1、2两题,第三天做3、4两题,第五天做5。在第六天的时候所有钱都付完。

    数据范围:

    对于100%的数据:1<=n<=300,1<=aibi<=m<=1000。

    ————————————————我是分割线————————————————

    神奇的题目!最坑了!

    看上去怎么都可以贪心。。但是其实不行的QAQ

    比如说:

    ————————————————我是分割线————————————————

    T4:短

      给出一张有n个点和m条双向边的图,要求求出1到n的次短路的长度。一条边可以多次通过。

    输入格式:

    第一行为两个整数n和m。接下来的m行每行三个整数ai,bi,vi,分别表示这条路连着的两个点和他的长度。

    输出格式:

    一个整数,表示次短路的长度。

    样例输入

    样例输出

    4 4
    1 2 100
    2 4 200
    2 3 250
    3 4 100

    450

    样例解释:

    最短:1->2->4。

    次短:1->2->3->4。

    数据范围:

    对于 100%的数据:1<=n、vi<=50001<=m<=100000

    ————————————————我是分割线————————————————

    暴力dij,不解释,本场最水的题目

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define MN 200005
    #define M 5005
    using namespace std;
    int head[M],d1[M],d2[M],n,m,num;
    struct e{
        int to,next,w;
    }g[MN];
    void ins(int u,int v,int val){g[++num].next=head[u];head[u]=num;g[num].to=v;g[num].w=val;}
    void insw(int u,int v,int w){ins(u,v,w);ins(v,u,w);}
    void swap(int &a,int &b){a^=b;b^=a;a^=b;}
    struct edge{
        int to,value;
        edge(int to,int value):to(to),value(value) {}
        friend bool operator <(edge a,edge b){
            return a.value>b.value;
        }
    };
    priority_queue<edge>q;
    void dij(){
        d1[1]=0;q.push(edge(1,0));
        while(!q.empty()){
            edge tmp=q.top();q.pop();if(tmp.value>d2[tmp.to])continue;
            for(int i=head[tmp.to];i;i=g[i].next){
                int dd=tmp.value+g[i].w;
                if(dd==d1[g[i].to])continue;
                if(dd<d1[g[i].to]){
                    swap(dd,d1[g[i].to]);
                    q.push(edge(g[i].to,d1[g[i].to]));
                }
                if(dd<d2[g[i].to]){
                    swap(dd,d2[g[i].to]);
                    q.push(edge(g[i].to,d2[g[i].to]));
                }
            }
        }
    }
    int main(){
        freopen("short.in","r",stdin);
        freopen("short.out","w",stdout);
        scanf("%d%d",&n,&m);memset(d1,0x3f,sizeof(d1));memset(d2,0x3f,sizeof(d2));
        int x,y,val;
        for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&val),insw(x,y,val);
        dij(),printf("%d
    ",d2[n]);
        return 0;
        fclose(stdin);
        fclose(stdout);
    }
  • 相关阅读:
    并查集_贪心_求无向图最短连通路径_最小生成树(kruskal)
    01背包&&完全背包_顺序枚举和逆序枚举的问题_一维数组
    week7_简单题_C_水题_hdu_5578+F_贪心_hdu_5583
    计量经济学_大纲
    概率专题_概率/ 数学_基础题_ABEI
    动态规划_01背包_从Dijikstra和Floyd入手,彻底理解01背包
    动态规划_基础_最长公共子序列_多种方法_递归/dp
    动态规划_基础_分治思想_从归并排序到任意子区间序列求和_滑动窗口+递推
    分治思想_归并排序_各种写法和思路(待续)
    递归基础_整数划分类问题_ 多状态转移复杂递推
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/7598103.html
Copyright © 2011-2022 走看看