9.24 AHSOFNU 校内模拟

  //看起来养成了不好的风气 ,只更切菜杯?

    好啦其实其他的好没有整理好... 而且切菜杯比较顺手

    嗯下面进入正题  请各位倒着切题(lrb学长的特性)

个人卫生综合征

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

Other:

  比起下面可爱的题目绝对算是丧题了。

  比较可惜的是好像暴力可以打一点点分... 不过时间都在跑t2的表上了

Solution:

  建分层图。

  把整张复制k次,跑dij。

  //然而有思路的我还没打... 学长代码先贴上(待更新)

 1 //学长代码...等待更新
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <queue>
 6 #define INF 0x3f3f3f3f
 7  
 8 struct path
 9 {
10     int to,v;
11 };
12 struct node
13 {
14     int num,v;
15     bool operator <(const node &b) const
16     {
17        return v>b.v;
18     }
19 };
20 std::vector<path> g[10001];
21 std::priority_queue<node> q;
22 int m,n,k,ans;
23 int dist[10001][21];
24 bool vis[10001][21];
25 
26 int getint()
27 {
28     int x=0,f=1;
29     char ch=getchar();
30     while(ch<'0'||ch>'9')
31     {
32         if(ch=='-') f=-f;
33         ch=getchar();
34     }
35     while(ch>='0'&&ch<='9')
36     {
37         x=x*10+ch-'0';
38         ch=getchar();
39     }
40     return x*f;
41 }
42  
43 int min(int a,int b)
44 {
45     return a<b?a:b;
46 }
47  
48 void dij()
49 {
50     node now;
51     memset(dist,INF,sizeof(dist));
52     memset(vis,false,sizeof(vis));
53     dist[1][0]=0;
54     q.push((node){1,0});
55     while(!q.empty())
56     {
57         now=q.top();
58         q.pop();
59         int t1=now.num%(n+1),t2=now.num/(n+1);
60         vis[t1][t2]=true;
61         for(int i=0;i<int(g[t1].size());i++)
62         {
63             path t=g[t1][i];
64             if((!vis[t.to][t2])&&dist[t.to][t2]>dist[t1][t2]+t.v)
65             {
66                 dist[t.to][t2]=dist[t1][t2]+t.v;
67                 q.push((node){t2*(n+1)+t.to,dist[t.to][t2]});
68             }
69             if((!vis[t.to][t2+1])&&t2<k&&dist[t.to][t2+1]>dist[t1][t2])
70             {
71                 dist[t.to][t2+1]=dist[t1][t2];
72                 q.push((node){(t2+1)*(n+1)+t.to,dist[t.to][t2+1]});
73             }
74         }
75     }
76 }
77  
78 int main()
79 {
80     freopen("school.in","r",stdin);
81     freopen("school.out","w",stdout);
82     n=getint(),m=getint(),k=getint();
83     for(int i=1;i<=m;i++)
84     {
85         int a=getint(),b=getint(),v=getint();
86         g[a].push_back((path){b,v});
87         g[b].push_back((path){a,v});
88     }
89     dij();
90     ans=INF;
91     for(int i=0;i<=k;i++) ans=min(ans,dist[n][i]);
92     printf("%d",ans);
93     return 0;
94 }

你的四边形已如风中残烛

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

 

输入格式:

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

输出格式:

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

样例输入

样例输出

6

6

样例解释:

11221212,1221,2112,2121,2211。

数据范围:

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

Other:

  数学题。

  想不出正解的只能好好打表。然而打表的优化不够,跑了一个多小时...(打表技巧有待提升)

  机房大佬lzb一个表跑300s+就结束了(%%%)。

  下面是lzb大佬的打表机。

  

 1 //lzb的打表机
 2 #include<cstdio>
 3 using namespace std;
 4 int main(){
 5     freopen("bll.out","w",stdout);
 6     for(int n=0;n<=2500;n++){
 7         long long ans=0;
 8         for(int i=1;i<=n/4;i++)
 9             for(int j=i;j<=(n-i)/3;j++)
10                 for(int k=j;k<=(n-i-j)/2;k++)if(n-i-j-k<i+j+k){
11                     if(i==j&&j==k&&k==n-i-j-k)ans++;
12                     else if((i==j&&j==k)||(j==k&&k==n-i-j-k))ans+=4;
13                     else if(i==j&&k==n-i-j-k)ans+=6;
14                     else if(i==j||k==n-i-j-k||j==k)ans+=12;
15                     else ans+=24;
16                 }
17         printf("%lld,",ans);
18     }
19 }

Solution:

  接下来是正解。

  f[i][j]用来表示在i时分成j段的方案数,然后进行转移。

 1 #include<cstdio>
 2 #define MAXN 2505
 3 #define Min(a,b) (a<b?a:b)
 4 using namespace std;
 5 int f[MAXN][5];
 6 int n,mid;
 7 int main(){
 8     freopen("quad.in","r",stdin);
 9     freopen("quad.out","w",stdout);
10     scanf("%d",&n);
11     mid=(n-1)>>1;
12     f[0][0]=1;
13     for(int i=1;i<=n;i++)
14         for(int j=1;j<=4;j++) 
15             for(int k=1;k<=Min(mid,i);k++) f[i][j]+=f[i-k][j-1];
16     printf("%d",f[n][4]);
17     return 0;
18 }

生命不息刷题不止

 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

Other:

  坑题啊。蒟蒻先留坑。

Solution:

  

  给出一张有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

Solution:

  题面很清楚的说出来是最短路啦~

  对于次短路,我们可以用d[i]记录最短路,而最短路节点的上一个,即次短路的距离用d2[i]来记录。

  次短路有两种情况:首先走di[i]到i然后从i到j,再走d2[j]到n;走d[i]i,然后从i到j再到i,再走d2[i]n。

  然后直接跑dij就可以啦~

  (机房大佬OMG_link SPFA被卡40嘿嘿嘿)

 1 #include<cstdio>
 2 #include<queue>
 3 #include<map>
 4 #include<vector>
 5 #include<algorithm>
 6 #define INF 0x7fffffff
 7 #define Max_v 5005
 8 using namespace std;
 9 struct edge{int to,cost;};
10 typedef pair<int,int> P; 
11 int V,E;
12 vector <edge> G[Max_v];
13 int d[Max_v];
14 int d2[Max_v];
15 void dijstra(int s){
16     priority_queue<P,vector<P>,greater<P> >que;
17     fill(d,d+V,INF);
18     fill(d2,d2+V,INF);
19     d[s]=0;
20     que.push(P(0,s));    
21     while(!que.empty()){        
22         P p=que.top();que.pop();
23         int v=p.second;           
24         for(int i=0;i<G[v].size();i++){
25             edge e=G[v][i];
26             int dd=p.first+G[v][i].cost;
27             if(d[e.to]>d[v]+e.cost){
28                 d[e.to]^=dd;dd^=d[e.to];d[e.to]^=dd;
29                 que.push(P(d[e.to],e.to));
30             }
31             if(dd<d2[e.to] && dd>d[e.to]){
32                 d2[e.to]=dd;
33                 que.push(P(d2[e.to],e.to));
34             }
35         }
36     }
37 }
38 int main(){
39     freopen("short.in","r",stdin);
40     freopen("short.out","w",stdout);
41     int x,y,w;
42     scanf("%d%d",&V,&E);
43     for(int i=0;i<E;i++){
44         scanf("%d%d%d",&x,&y,&w);
45         x-=1;y-=1;
46         edge e;
47         e.to=y;e.cost=w;G[x].push_back(e);
48         e.to=x;e.cost=w;G[y].push_back(e);
49     }
50     dijstra(0);    
51     printf("%d",d2[V-1]);
52     return 0;
53 }

  

原文地址:https://www.cnblogs.com/drizzly/p/7616423.html