2017.9.17机房欢乐模拟赛 解题报告

巧克力棒(chocolate)

Time Limit:1000ms Memory Limit:64MB

题目描述

LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去。

具体地,这根巧克力棒长为 n,它想将这根巧克力棒折成 n 段长为 1 的巧克力棒,然后

慢慢享用。

它打算每次将一根长为 k 的巧克力棒折成两段长为 a 和 b 的巧克力棒,此时若 a=b,则

LYK 觉得它完成了一件非常困难的事,并会得到 1 点成就感。

LYK 想知道一根长度为 n 的巧克力棒能使它得到最多几点成就感。

输入格式(chocolate.in)

第一行一个数 n。

输出格式(chocolate.out)

一个数表示答案。

输入样例

7

输出样例

4

数据范围

对于 20%的数据 n<=5。

对于 50%的数据 n<=20。

对于 80%的数据 n<=2000。

对于 100%的数据 n<=1000000000。

样例解释

将 7 掰成 3+4, 将 3 掰成 1+2, 将 4 掰成 2+2 获得 1 点成就感, 将剩下的所有 2 掰成 1+1

获得 3 点成就感。总共 4 点成就感。

 

解析:

可以把问题倒过来考虑,与其折巧克力棒,不如拼巧克力棒。

以样例为例:把7看成7个点,每两个点可以合成一个点,那么7就能合成3个点,再将这3个点合成1个点,那么总共就是4个点。

其他数据同理。

每个数能够合成的点的数量为n/2.

代码:

 

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 long long n,ans;
 6 int main() {
 7     freopen("chocolate.in","r",stdin);
 8     freopen("chocolate.out","w",stdout);
 9     scanf("%lld",&n);
10     while(n>=2) {
11         n>>=1;
12         ans+=n;
13     }
14     printf("%lld",ans);
15     return 0;
16 }

 

LYK 快跑!(run)

Time Limit:5000ms Memory Limit:64MB

题目描述

LYK 陷进了一个迷宫! 这个迷宫是网格图形状的。 LYK 一开始在(1,1)位置, 出口在(n,m)。

而且这个迷宫里有很多怪兽,若第 a 行第 b 列有一个怪兽,且此时 LYK 处于第 c 行 d 列,此

时这个怪兽对它的威胁程度为|a-c|+|b-d|。

LYK 想找到一条路径,使得它能从(1,1)到达(n,m),且在途中对它威胁程度最小的怪兽的

威胁程度尽可能大。

当然若起点或者终点处有怪兽时,无论路径长什么样,威胁程度最小的怪兽始终=0。

输入格式(run.in)

第一行两个数 n,m。

接下来 n 行,每行 m 个数,如果该数为 0,则表示该位置没有怪兽,否则存在怪兽。

数据保证至少存在一个怪兽。

输入格式(run.out)

一个数表示答案。

输入样例

3 4

0 1 1 0

0 0 0 0

1 1 1 0

输出样例

1

数据范围

对于 20%的数据 n=1。

对于 40%的数据 n<=2。

对于 60%的数据 n,m<=10。

对于 80%的数据 n,m<=100。

对于 90%的数据 n,m<=1000。

对于另外 10%的数据 n,m<=1000 且怪兽数量<=100。

题解:

二分答案+bfs。

感觉写不出来就打了40分暴力。。

正解应该是这样的:

首先预处理出每个点到最近的怪物的距离 
BFS即可(刚开始把所有的怪物全部进队然后bfs) 
然后二分答案求解。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1010;
 8 int n,m,tot,a[maxn][maxn],v[maxn][maxn];
 9 int xx[5]={0,1,-1,0,0},
10     yy[5]={0,0,0,1,-1};
11 queue<int> x,y;
12 bool flag[maxn][maxn];
13 void color()
14 {
15     while(!x.empty())
16     {
17         int fx=x.front();
18         int fy=y.front();
19         x.pop();y.pop();
20         for(int i=1;i<=4;i++)
21         {
22             int tx=fx+xx[i];
23             int ty=fy+yy[i];
24             if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&!flag[tx][ty])
25             {
26                 flag[tx][ty]=1;
27                 v[tx][ty]=v[fx][fy]+1;
28                 x.push(tx);
29                 y.push(ty);
30             }
31         }
32     }
33 }
34 bool can(int mid)
35 {
36     for(int i=1;i<=n;i++)
37     for(int j=1;j<=m;j++)
38     flag[i][j]=0;
39     while(!x.empty()) x.pop();
40     while(!y.empty()) y.pop();
41     x.push(1);y.push(1);
42     flag[1][1]=1;
43     while(!x.empty())
44     {
45         int fx=x.front();
46         int fy=y.front();
47         x.pop(),y.pop();
48         for(int i=1;i<=4;i++)
49         {
50             int tx=fx+xx[i],ty=fy+yy[i];
51             if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&!flag[tx][ty]&&!a[tx][ty]&&v[tx][ty]>=mid)
52             {
53                 if(tx==n&&ty==m)
54                 return 1;
55                 flag[tx][ty]=1;
56                 x.push(tx);
57                 y.push(ty);
58             }
59         }
60     }
61     return 0;
62 }
63 int main()
64 {
65     freopen("run.in","r",stdin);
66     freopen("run.out","w",stdout);
67     scanf("%d%d",&n,&m);
68     for(int i=1;i<=n;i++)
69       for(int j=1;j<=m;j++)
70       {
71         cin>>a[i][j];
72         if(a[i][j]==1)
73         {
74             x.push(i);y.push(j);
75             flag[i][j]=1;v[i][j]=0;
76         }
77       }
78     color();
79     if(a[1][1]==1||a[n][m]==1)
80     {
81         cout<<0;
82         return 0;
83     }
84     int l=0,r=m*n,mid,ans=0;
85     while(l<=r)
86     {
87         mid=(l+r)>>1;
88         if(can(mid))
89         {
90             ans=mid;
91             l=mid+1;
92         }
93         else r=mid-1;
94     }
95     cout<<ans;
96     return 0;
97 }

 

仙人掌(cactus)

Time Limit:1000ms Memory Limit:64MB

题目描述

LYK 在冲刺清华集训(THUSC) !于是它开始研究仙人掌,它想来和你一起分享它最近

研究的结果。

 

 

如果在一个无向连通图中任意一条边至多属于一个简单环 (简单环的定义为每个点至多

经过一次) ,且不存在自环,我们称这个图为仙人掌。

LYK 觉得仙人掌还是太简单了,于是它定义了属于自己的仙人掌。

定义一张图为美妙的仙人掌, 当且仅当这张图是一个仙人掌且对于任意两个不同的点 i,j,

存在一条从 i 出发到 j 的路径,且经过的点的个数为|j-i|+1 个。

给定一张 n 个点 m 条边且没有自环的图,LYK 想知道美妙的仙人掌最多有多少条边。

数据保证整张图至少存在一个美妙的仙人掌。

输入格式(cactus.in)

第一行两个数 n,m 表示这张图的点数和边数。

接下来 m 行,每行两个数 u,v 表示存在一条连接 u,v 的无向边。

输出格式(cactus.out)

一个数表示答案

输入样例

4 6

1 2

1 3

1 4

2 3

2 4

3 4

输出样例

4

题解:

第一次提交30分 感觉很不服,然后把<改成了<=,cnt初始值设成1,瞬间到了80分。0.0

还有二十分蜜汁错误。

可能是我离线处理的原因???反正改成在线就对了。0.0

因为数据保证整张图至少存在一个美妙的仙人掌,所以第i个点和第i+1个点一定是连着的。

至少有n-1条边

然后使它尽可能多的方法就是在一条路径上(第i个点到第j个点)不能有两条路径重叠。

以样例为例,选择边 1-2,1-3,2-3,3-4,而不能添加边的原因是:如果再添加一条边(比如1-4),就会有1-3这条边存在于两个简单环中,是不符合要求的,其原因就是1-4和3-4有重叠部分。所以我们让它没有重叠部分的方法就转化成了线段覆盖问题。

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #define maxn 100005
 5 using namespace std;
 6 struct Node {
 7     int x,y;
 8 }node[maxn];
 9 int comp(Node a,Node b) {
10     if(a.y == b.y) return a.x<b.x;
11     return a.y<b.y;
12 }
13 int n,m,Cnt;
14 int main() {
15     freopen("cactus.in","r",stdin);
16     freopen("cactus.out","w",stdout);
17     scanf("%d%d",&n,&m);
18     for(int i=1;i<=m;i++) {
19         int x,y;
20         scanf("%d%d",&x,&y);
21         if(x>y) swap(x,y);
22         if(x+1!=y) node[++Cnt].x=x,node[Cnt].y=y;
23     }
24     sort(node+1,node+1+Cnt,comp);
25     int ans=0,tot=0,e=0;
26     for(int i=1;i<=Cnt;i++) {
27         if(e<=node[i].x) {
28             e=node[i].y;
29             tot++;
30         }
31     }
32     ans=tot+n-1;
33     printf("%d",ans);
34     return 0;
35 }

 

posted @ 2017-09-17 21:24  Ruler❀  阅读(224)  评论(0编辑  收藏  举报