• 2017.09.24校内训练


    T1:个人卫生综合征

    题目描述:

    每天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。

    题解:建分层图,然后跑最短路即可。看代码即可理解。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 struct path{
    12     int to,val;
    13 };
    14 struct node{
    15     int num,v;
    16     bool operator <(const node &b) const{
    17         return v>b.v;
    18     }
    19 };
    20 std::vector<path> g[10010];
    21 std::priority_queue<node> q;
    22 int m,n,k,ans;
    23 int dist[10010][25];
    24 bool vis[10010][25];
    25 void dij(){
    26     node now;
    27     memset(dist,inf,sizeof(dist));
    28     memset(vis,0,sizeof(vis));
    29     dist[1][0]=0;
    30     int i,j;
    31     q.push((node){1,0});
    32     while(!q.empty()){
    33         now=q.top();q.pop();
    34         int ta=now.num%(n+1),tb=now.num/(n+1);
    35         vis[ta][tb]=true;
    36         for(i=0;i<int(g[ta].size());++i){
    37             path t=g[ta][i];
    38             if(!vis[t.to][tb] && dist[t.to][tb]>dist[ta][tb]+t.val){
    39                 dist[t.to][tb]=dist[ta][tb]+t.val;
    40                 q.push((node){tb*(n+1)+t.to,dist[t.to][tb]});
    41             }
    42             if(!vis[t.to][tb+1] && tb<k && dist[t.to][tb+1]>dist[ta][tb]){
    43                 dist[t.to][tb+1]=dist[ta][tb];
    44                 q.push((node){(tb+1)*(n+1)+t.to,dist[t.to][tb+1]});
    45             }
    46         }
    47     }
    48 }
    49 int main(){
    50     freopen("school.in","r",stdin);
    51     freopen("school.out","w",stdout);
    52     scanf("%d%d%d",&n,&m,&k);
    53     int i,j;
    54     int a,b,v;
    55     for(i=1;i<=m;++i){
    56         scanf("%d%d%d",&a,&b,&v);
    57         g[a].push_back((path){b,v});
    58         g[b].push_back((path){a,v});
    59     }
    60     dij();
    61     ans=inf;
    62     for(i=0;i<=k;++i)  ans=min(ans,dist[n][i]);
    63     printf("%d\n",ans);
    64     return 0;
    65 }
    school

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

    题目描述:

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

    输入格式:

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

    输出格式:

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

    样例输入

    样例输出

    6

    6

    样例解释:

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

    数据范围:

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

    题解:记dp[i][j]为长度为i时分成j段的方案数,注意一段长度小于总长的一般。dp[i][j]可以从dp[i-k][j-1]转移而来(k表示单段长度)。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 using namespace std;
     8 int n,mid;
     9 int dp[2510][5];
    10 int min(int a,int b){
    11     return a<b?a:b;
    12 }
    13 int main(){
    14     freopen("quad.in","r",stdin);
    15     freopen("quad.out","w",stdout);
    16     scanf("%d",&n);
    17     memset(dp,0,sizeof(dp));
    18     mid=(n-1)>>1;
    19     dp[0][0]=1;
    20     int i,j,k;
    21     for(i=1;i<=n;++i){
    22         for(j=1;j<=4;++j){
    23             for(k=1;k<=min(i,mid);++k){
    24                 dp[i][j]+=dp[i-k][j-1];
    25             }
    26         }
    27     }
    28     printf("%d\n",dp[n][4]);
    29     return 0;
    30 }
    View Code

    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行每一行都有两个数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。

    题解:记dp[i][j]为前i天做了j道题第i天最多能够剩下的钱的数量。因此,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即可。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #define inf 0x3f3f3f3f
     8 using namespace std;
     9 int n,m;
    10 int ta,tb;
    11 int max(int a,int b){
    12     return a>b?a:b;
    13 }
    14 int dp[1010][310];
    15 int a[310],b[310];
    16 int main(){
    17     freopen("solve.in","r",stdin);
    18     freopen("solve.out","w",stdout);
    19     scanf("%d%d",&m,&n);
    20     int j;
    21     for(int i=1;i<=n;++i){
    22         scanf("%d%d",&a[i],&b[i]);
    23     }
    24     memset(dp,inf,sizeof(dp));
    25     dp[2][0]=m;
    26     int i=2;
    27     while(dp[i][n]==inf){
    28         for(j=n;j>=0;j--){
    29             if(dp[i][j]!=inf){
    30                 int k=j+1;
    31                 ta=dp[i][j];tb=dp[i+1][j]=m;
    32                 while(ta>=a[k] && tb>=b[k]){
    33                     ta-=a[k];tb-=b[k];
    34                     dp[i][k]=(dp[i][k]==inf?ta:max(dp[i][k],ta));
    35                     dp[i+1][k]=(dp[i+1][k]==inf?tb:max(dp[i+1][k],tb));
    36                     k++;
    37                 }
    38             }
    39         }
    40         i++;
    41     }
    42     printf("%d\n",i);
    43     return 0;
    44 }
    View Code

    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<=5000,1<=m<=100000。

    题解:考虑dist[i]为1到i的最短路,dist2[i]表示从i到n的最短路次短路有两种情况:一是从1走dist[i]到i,从i到j,走dist2[j]到n;二是从1走dist[i]到i,从i到j再回到i,走dist2[i]到n,暴力枚举即可(似乎dij也有一种算法,但我打挂了)。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<algorithm>
      5 #include<iostream>
      6 #include<cmath>
      7 #include<queue>
      8 #define inf 0x3f3f3f3f
      9 struct path
     10 {
     11     int from,to,v,next;
     12 }g[200001];
     13 int min(int a,int b){
     14     return a<b?a:b;
     15 }
     16 std::queue<int> q;
     17 int n,m,tot,mn,ans;
     18 int last[5001],dist[5001],dist2[5001];
     19 bool inq[5001];
     20 void ins(int a,int b,int v)
     21 {
     22     g[++tot].from=a;g[tot].to=b;g[tot].v=v;g[tot].next=last[a];last[a]=tot;
     23     g[++tot].from=b;g[tot].to=a;g[tot].v=v;g[tot].next=last[b];last[b]=tot;
     24 }
     25 void spfa()
     26 {
     27     memset(inq,false,sizeof(inq));
     28     memset(dist,inf,sizeof(dist));
     29     dist[1]=0;
     30     q.push(1);
     31     inq[1]=true;
     32     while(!q.empty())
     33     {
     34         int now=q.front();
     35         q.pop();
     36         inq[now]=false;
     37         for(int i=last[now];i>0;i=g[i].next)
     38         {
     39             int t=g[i].to;
     40             if(dist[t]>dist[now]+g[i].v)
     41             {
     42                 dist[t]=dist[now]+g[i].v;
     43                 if(!inq[t])
     44                 {
     45                     q.push(t);
     46                     inq[t]=true;
     47                 }
     48             }
     49         }
     50     }
     51 }
     52 void spfa2()
     53 {
     54     memset(inq,false,sizeof(inq));
     55     memset(dist2,inf,sizeof(dist));
     56     dist2[n]=0;
     57     q.push(n);
     58     inq[n]=true;
     59     while(!q.empty())
     60     {
     61         int now=q.front();
     62         q.pop();
     63         inq[now]=false;
     64         for(int i=last[now];i>0;i=g[i].next)
     65         {
     66             int t=g[i].to;
     67             if(dist2[t]>dist2[now]+g[i].v)
     68             {
     69                 dist2[t]=dist2[now]+g[i].v;
     70                 if(!inq[t])
     71                 {
     72                     q.push(t);
     73                     inq[t]=true;
     74                 }
     75             }
     76         }
     77     }
     78 }
     79 int main()
     80 {
     81     freopen("short.in","r",stdin);
     82     freopen("short.out","w",stdout);
     83     scanf("%d%d",&n,&m);
     84     for(int i=1;i<=m;i++)
     85     {
     86         int x,y,l;
     87         scanf("%d%d%d",&x,&y,&l);
     88         ins(x,y,l);
     89     }
     90     spfa();
     91     mn=dist[n];
     92     spfa2();
     93     ans=inf;
     94     for(int i=1;i<=tot;i++)
     95     {
     96         int l=dist[g[i].from]+dist2[g[i].to]+g[i].v;
     97         if(l<ans&&l>mn) ans=l;
     98     }
     99     for(int i=1;i<=tot;i++)
    100         ans=min(ans,dist[g[i].from]+dist2[g[i].from]+2*g[i].v);
    101     printf("%d",ans);
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    ajax的原理及实现方式
    在linux中添加环境变量
    ftp简单命令
    linux命令之scp
    java中创建对象的方法
    10个调试技巧
    java读取.properties配置文件的几种方法
    Java对象和XML转换
    Java Float类型 减法运算时精度丢失问题
    Java内存分配全面浅析
  • 原文地址:https://www.cnblogs.com/lazytear/p/7597960.html
Copyright © 2020-2023  润新知