一本通1423 种树

Posted qianr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一本通1423 种树相关的知识,希望对你有一定的参考价值。

技术图片

 

 技术图片

 

 这道题是一个典型的区间选点问题。每一个房子代表一个要求,这个要求对应着一个左端点和右端点,以及一个要求的树数。它就相当于是给定一个区间,在这个区间内插入要求的点数。求的种数的最小数量即为总点数。

这样我们就可以将这个问题转化为一个区间选点问题并得出基本思路。

基本思路:种树要种得少,就要尽量让一棵树处在多个区间内。这样,我们只需要尽量在重叠区间种树即可。而重叠部分一定位于区间尾部。因此,我们可以先按照所有区间的结束位置进行排序,之后依次处理每一个区间,先在一个区间的尾部种满足够的树,对下一个区间,只需要判断还需要多少棵树就在区间的尾部中多少就可以

下面写代码。

首先我们需要定义好需要的变量。定义n表示区域个数,m表示房子的数目,ans表示种树的最小数量,同时开一个i方便输入。

同时我们需要定义一个结构体来存储每一个种树的需求。设l表示需求的左边界,r表示需求的右边界,need表示需要的树的数量,然后进行输入输出。

得出代码如下:

 1 #include<iostream>
 2 using namespace std;
 3 int n,m,i,ans; 
 4 struct xuqiu{
 5     int l;
 6     int r;
 7     int need;
 8 }t[5005];
 9 int main(){
10     cin>>n>>m;
11     for(i=1;i<=m;i++){
12         cin>>t[i].l>>t[i].r>>t[i].need;
13     }
14     return 0;
15 }

接下来按照我们的思路,我们需要按照所有需求的右边界进行一遍排序,方便后续将树从小到大进行插入。这里需要手写cmp函数。

得出代码如下:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 int n,m,i,ans;
 5 struct xuqiu{
 6     int l;
 7     int r;
 8     int need;
 9 }t[5005];
10 bool cmp(xuqiu a,xuqiu b){
11     if(a.r<b.r){
12         return true;
13     }else{
14         return false;
15     }
16 }
17 int main(){
18     cin>>n>>m;
19     for(i=1;i<=m;i++){
20         cin>>t[i].l>>t[i].r>>t[i].need;
21     }
22     sort(t+1,t+m+1,cmp);
23     return 0;
24 }

然后我们就要进入主要的环节了。首先,我们需要对ans进行初始化。为了方便,我们要开一个bool数组used来表示该点是否已经种上了树,其中true表示该点已有树,false表示该点没有树。然后我们枚举每一个需求,并设置一个新变量k来表示当前这个需求的区间里已有多少棵树。我们开一个变量j来对这个需求的区间进行枚举,先记录下已有的树的数量。如果已有树的数量大于等于所需树的数量,该要求已经满足,可以将它continue掉,否则从右边界向左边界进行枚举,判断如果该点没有种过树,就种上树。直到树的数目足够为止。最后将答案输出即可。

下面是完整代码(含注释):

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 int n,m,i,j,k,ans;
 5 bool used[30005]={0};//记录该位置是否有树,有为true,没有为false 
 6 struct xuqiu{
 7     int l;
 8     int r;
 9     int need;
10 }t[5005];
11 bool cmp(xuqiu a,xuqiu b){
12     if(a.r<b.r){
13         return true;
14     }else{
15         return false;
16     }
17 }
18 int main(){
19     cin>>n>>m;
20     for(i=1;i<=m;i++){
21         cin>>t[i].l>>t[i].r>>t[i].need;
22     }
23     sort(t+1,t+m+1,cmp);
24     ans=0;//记录树的总数
25     for(i=1;i<=m;i++){
26         k=0;
27         for(j=t[i].l;j<=t[i].r;j++){
28             if(used[j]==true){//记录这个需求的左边界到右边界内已有树的数目 
29                 k++;
30             }
31         }
32         if(k>=t[i].need){//树的数目足够
33             continue;
34         }
35         for(j=t[i].r;j>=t[i].l;j--){//否则从右向左进行种树
36             if(used[j]==false){//如果这个地方没有种过树 
37                 used[j]=true;
38                 k++;
39                 ans++;//多种了一棵树
40             }
41             if(k==t[i].need){//达到了树的需求量
42                 break;
43             }
44         }
45     }
46     cout<<ans<<endl;
47     return 0;
48 }

这样这道题就通过了。

以上是关于一本通1423 种树的主要内容,如果未能解决你的问题,请参考以下文章

一本通1537校门外的树

《信奥一本通》提高版—简要题解

一本通网站基础篇完结纪念

一本通1154:亲和数

一本通题1051

一本通1058:求一元二次方程