zoukankan      html  css  js  c++  java
  • 20170924校内训练

    个人卫生综合征

    每天BBS都要从家里经过城市中的一段路到学校刷五三。城市中一共有n个路口和m条双向道路,每条双向道路都连接着两个路口ai、bi且有一定的时间花费vi。BBS家编号为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<=20,1<=vi<=1000000。 

    dijsktra。用d[i][j]表示i点与1号点用了j次魔法的距离

    更新时,d[i.to][j]=d[i][j]+cost[i][j](不用魔法),d[i.to][j+1]=d[i][j](j+1<k)(用魔法)

    入堆时,再记下当前用了多少次魔法。即pair<int,pair<int,int> > 第一个int记距离,第二的int记使用魔法次数,第三个int记标号

    岀堆的条件改为距离>dist[标号][使用魔法次数]

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef pair<int,int> p;
    typedef pair<int,p>P;
    priority_queue<P,vector<P>,greater<P> >q;
    int n,m,k;
    int dist[10010][25];
    int h[10010],to[100010],next[100010],cost[100010],tot=0;
    void ins(int u,int v,int w){next[++tot]=h[u];h[u]=tot;to[tot]=v;cost[tot]=w;}
    void dij(int S)
    {
        memset(dist,127,sizeof(dist));
        for(int i=0;i<=k;i++)dist[S][i]=0,q.push(P(0,p(i,S)));
        while(!q.empty())
        {
            P pp=q.top();q.pop();int K=pp.second.first,u=pp.second.second,d=pp.first;
            if(d>dist[u][K])continue;
            for(int i=h[u];i;i=next[i])
            {
                int v=to[i];
                if(dist[v][K]>d+cost[i]){dist[v][K]=d+cost[i];q.push(P(dist[v][K],p(K,v)));}
                if(K+1<=k&&dist[v][K+1]>d){dist[v][K+1]=d;q.push(P(dist[v][K+1],p(K+1,v)));}
            }
        }
    }
    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++)
        {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);ins(x,y,z);ins(y,x,z);
        }
        dij(1);printf("%d",dist[n][k]);
        return 0;
    }
    View Code

    你的四边形已如风中残烛

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

     输入格式:

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

    输出格式:

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

    样例输入

    样例输出

    6

    6

    样例解释:

           1122,1212,1221,2112,2121,2211。

    数据范围:

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

    打表大法好。或者你可以推通项公式。或者枚举前两个长度计算答案(这个比起推通项公式容易一点)。

    总之,这道题的核心是,假设你取的四个木板长为a,b,c,d,它们能构成四边形要满足

    a+b+c>d,a+b+d>c,a+c+d>b,b+c+d>a

    我们可以发现a<n/2,b<n/2,c<n/2,d<n/2,就用这玩意去算答案

    #include<cstdio>
    long long n;
    int main(){
        //freopen("quad.in","r",stdin);freopen("quad.out","w",stdout);
        scanf("%lld",&n);
        printf("%lld",((n-3)*(n-2)*(n-1))/6-2*((n/2)*((n/2)-1)*((n/2)-2))/3);
        return 0;
    }
    View Code

    生命不息刷题不止

     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行每一行都有两个数ai和bi,分别表示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<=ai、bi<=m<=1000。

    这道题不能贪心!这道题不能贪心!这道题不能贪心!重要的事情说三遍

    10 3

    3 5

    2 5

    2 5

    贪心的答案是5,第2天做1,2两题,第3天还债,第4天做第3题,第5天还债

    而实际上只要4天,第2天做第1题,第3天做2,3两题,第4天还债

    正确思路是dp

    设dp[i][j]表示前i天做了j题后该天可能剩下的最多的钱的数量。

    那么dp[i][j]可以转移到dp[i][j+1]、dp[i][j+2]……只要满足剩下的钱不少于0并且下个月的钱够还即可。

    同时可以算出dp[i+1][j+1],dp[i+1][j+2]……最后输出满足dp[i][m]存在值的最小i。

    #include<iostream>
    #include<cstdio> 
    #include<cstring>
    using namespace std;
    int dp[610][301],a[301],b[301];
    int main()
    {
        freopen("solve.in","r",stdin);freopen("solve.out","w",stdout);
        memset(dp,-1,sizeof(dp));
        int m,n;scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);
        dp[2][0]=m;
        for(int i=2;i<=2*n+1;i++)
        {
            for(int j=n;j>=0;j--)
            {
                if(dp[i][j]!=-1)
                {
                    dp[i+1][j]=m;int tot1=0,tot2=0;
                    for(int k=j+1;k<=n;k++)
                    {
                        tot1+=a[k];tot2+=b[k];
                        if(tot1>dp[i][j]||tot2>m)break;
                        dp[i][k]=max(dp[i][k],dp[i][j]-tot1);
                        dp[i+1][k]=max(dp[i+1][k],m-tot2);
                    }
                }
            }
            if(dp[i][n]!=-1)return 0*printf("%d",i+1);
        }    
        return 0;
    }
    View Code

    给出一张有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<=5000,1<=m<=100000。 

    裸次短路

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    int h[5100],to[200100],next[200100],k=0,cost[200100];
    typedef pair<int,int> P;
    priority_queue<P,vector<P>,greater<P> > q;
    int dist[5100][2];
    void ins(int u,int v,int w){next[++k]=h[u];h[u]=k;to[k]=v;cost[k]=w;}
    void dij(int S)
    {
        memset(dist,127/2,sizeof(dist));
        dist[S][0]=0;q.push(P(0,S)); 
        while(!q.empty())
        {
            P p=q.top();q.pop();int u=p.second;
            if(dist[u][1]<p.first)continue;
            for(int i=h[u];i;i=next[i])
            {
                int v=to[i];
                if(p.first+cost[i]<dist[v][0])
                {
                    dist[v][1]=dist[v][0];dist[v][0]=p.first+cost[i];
                    q.push(P(dist[v][0],v));q.push(P(dist[v][1],v)); 
                }
                else if(p.first+cost[i]<dist[v][1]&&p.first+cost[i]!=dist[v][0])
                {
                    dist[v][1]=p.first+cost[i];
                    q.push(P(dist[v][1],v)); 
                }
            }
        }
    }
    int main()
    {
        freopen("short.in","r",stdin);freopen("short.out","w",stdout);
        int n,m;scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);ins(x,y,z);ins(y,x,z);
        }
        dij(1);
        printf("%d",dist[n][1]);
        return 0;
    }
    View Code
  • 相关阅读:
    python学习笔记(五)
    python学习笔记(四)
    Jenkins学习系列——iOS打包任务的创建和配置
    Jenkins学习系列——jenkins平台搭建和配置
    java及java web学习笔记
    mac book下批量替换多个文件中的字符
    MAC的sed和GNU不一样
    python杂记
    appium ios环境搭建——iOS开发环境搭建
    ideviceinstaller报Segmentation fault: 11错误解决过程
  • 原文地址:https://www.cnblogs.com/lher/p/7620283.html
Copyright © 2011-2022 走看看