生活随笔
收集整理的這篇文章主要介紹了
第六章 贪心 【完结】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
貪心類題型沒有固定的模板只有多做題,總結經驗。
基本都熟練了
目錄
- 905. 區間選點
- 908. 最大不相交區間數量
- 906. 區間分組 【有意思】
- 907. 區間覆蓋【有意思】
- 148. 合并果子
- 913. 排隊打水
- 104. 貨倉選址
- 125. 耍雜技的牛
905. 區間選點
https://www.acwing.com/problem/content/description/907/
本題和區間合并那種題幾乎一樣的思路,不過還是有差別的。
首先:按左端點從小到達排,這是沒有懸念的必須做的。
這時候分析,會有如下幾種情況:
情況一:
這種包含的情況,我們要選小的,因為我們要的是公共部分。
情況二:
這種相交的情況選,相交的。
情況三:
不相交的情況選b,個數加1。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
struct student
{int x
,y
;
}stu
[N
];
bool cmp(student a
,student b
)
{return a
.x
<b
.x
;
}
int main(void)
{int n
; cin
>>n
;for(int i
=0;i
<n
;i
++) cin
>>stu
[i
].x
>>stu
[i
].y
;sort(stu
,stu
+n
,cmp
);int ans
=1;int startx
=stu
[0].x
,endx
=stu
[0].y
;for(int i
=1;i
<n
;i
++){if(stu
[i
].x
<=endx
&&stu
[i
].y
<=endx
) startx
=stu
[i
].x
,endx
=stu
[i
].y
;else if(stu
[i
].x
<=endx
&&stu
[i
].y
>endx
) startx
=stu
[i
].x
;else ans
++,startx
=stu
[i
].x
,endx
=stu
[i
].y
;}cout
<<ans
<<endl
;return 0;
}
#include<bits/stdc++.h>
using namespace std
;
typedef pair
<int,int> PII
;
vector
<PII
> ve
;
int main(void)
{int n
; cin
>>n
;while(n
--){int l
,r
; cin
>>l
>>r
;ve
.push_back({l
,r
});}sort(ve
.begin(),ve
.end());int ans
=0;int l
=-1e9-10,r
=-1e9-5;for(int i
=0;i
<ve
.size();i
++){if(ve
[i
].first
>r
) l
=ve
[i
].first
,r
=ve
[i
].second
,ans
++;else if(ve
[i
].second
<=r
) l
=ve
[i
].first
,r
=ve
[i
].second
;else if(ve
[i
].first
<=r
&&ve
[i
].second
>=r
) l
=ve
[i
].first
;}cout
<<ans
<<endl
;return 0;
}
方法二 從小到大排序右端點:
因為我們選右端點,才可能盡量大的覆蓋掉后面的區間
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std
;
const int N
=1e5+10;
struct node
{int x
,y
;
}Node
[N
];
bool cmp(node a
,node b
)
{return a
.y
<b
.y
;
}
int main(void)
{int n
; cin
>>n
;for(int i
=0;i
<n
;i
++) cin
>>Node
[i
].x
>>Node
[i
].y
;sort(Node
,Node
+n
,cmp
);int ans
=0;int flag
=-1e9;for(int i
=0;i
<n
;i
++){if(flag
<Node
[i
].x
) ans
++,flag
=Node
[i
].y
;}cout
<<ans
<<endl
;return 0;
}
#include<bits/stdc++.h>
using namespace std
;
typedef pair
<int,int> PII
;
vector
<PII
> ve
;
int main(void)
{int n
; cin
>>n
;while(n
--){int l
,r
; cin
>>l
>>r
;ve
.push_back({r
,l
});}int flag
=-1e9;int ans
=0;sort(ve
.begin(),ve
.end());for(int i
=0;i
<ve
.size();i
++) if(flag
<ve
[i
].second
) ans
++,flag
=ve
[i
].first
;cout
<<ans
<<endl
;return 0;
}
908. 最大不相交區間數量
https://www.acwing.com/problem/content/910/
老規矩:左端點從小到大排序
第一種情況:
這種得選a,這樣右邊的區間的選擇范圍才會更大。
第二種情況:
此時不用變,還是a這樣才會有更大的空間。
第三種情況:
選b,數量加1
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
struct student
{int x
,y
;
}stu
[N
];
bool cmp(student a
,student b
)
{return a
.x
<b
.x
;
}
int main(void)
{int n
; cin
>>n
;for(int i
=0;i
<n
;i
++) cin
>>stu
[i
].x
>>stu
[i
].y
;sort(stu
,stu
+n
,cmp
);int ans
=1;int startx
=stu
[0].x
,endx
=stu
[0].y
;for(int i
=1;i
<n
;i
++){if(stu
[i
].y
<endx
) startx
=stu
[i
].x
,endx
=stu
[i
].y
;else if(stu
[i
].x
>endx
) ans
++,startx
=stu
[i
].x
,endx
=stu
[i
].y
;}cout
<<ans
<<endl
;return 0;
}
方法二:從小到大排序右端點
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
struct node
{int x
,y
;
}Node
[N
];
bool cmp(node a
,node b
)
{return a
.y
<b
.y
;
}
int main(void)
{int n
; cin
>>n
;for(int i
=0;i
<n
;i
++) cin
>>Node
[i
].x
>>Node
[i
].y
;sort(Node
,Node
+n
,cmp
);int ans
=0;int flag
=-1e9;for(int i
=0;i
<n
;i
++){if(Node
[i
].x
>flag
) ans
++,flag
=Node
[i
].y
;}cout
<<ans
<<endl
;return 0;
}
#include<bits/stdc++.h>
using namespace std
;
vector
< pair
<int,int> > ve
;
int main(void)
{int n
; cin
>>n
;while(n
--){int l
,r
; cin
>>l
>>r
;ve
.push_back({r
,l
});}sort(ve
.begin(),ve
.end());int ans
=0;int flag
=-1e9-5;for(int i
=0;i
<ve
.size();i
++) if(ve
[i
].second
>flag
) ans
++,flag
=ve
[i
].first
;cout
<<ans
<<endl
;
}
906. 區間分組 【有意思】
https://www.acwing.com/problem/content/description/908/
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
struct node
{int x
,y
;
}Node
[N
];
bool cmp(node a
,node b
)
{return a
.x
<b
.x
;
}
int main(void)
{int n
; cin
>>n
;for(int i
=0;i
<n
;i
++) cin
>>Node
[i
].x
>>Node
[i
].y
;sort(Node
,Node
+n
,cmp
);priority_queue
<int, vector
<int>, greater
<int> >heap
;for(int i
=0;i
<n
;i
++){if(heap
.empty()||heap
.top()>=Node
[i
].x
){heap
.push(Node
[i
].y
);}else if(heap
.top()<Node
[i
].x
){heap
.pop();heap
.push(Node
[i
].y
);}}cout
<<heap
.size()<<endl
;return 0;
}
#include<bits/stdc++.h>
using namespace std
;
vector
< pair
<int,int> > ve
;
priority_queue
<int, vector
<int>, greater
<int> >heap
;
int l
,r
,n
;
int main(void)
{cin
>>n
;while(n
--) cin
>>l
>>r
, ve
.push_back({l
,r
});sort(ve
.begin(),ve
.end());for(int i
=0;i
<ve
.size();i
++){if(heap
.empty()||heap
.top()>=ve
[i
].first
) heap
.push(ve
[i
].second
);else if(heap
.top()<ve
[i
].first
) heap
.pop(),heap
.push(ve
[i
].second
);}cout
<<heap
.size()<<endl
;return 0;
}
907. 區間覆蓋【有意思】
https://www.acwing.com/problem/content/description/909/
對于可以覆蓋之前的,我們要選它們中最長的。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
struct node
{int x
,y
;
}Node
[N
];
bool cmp(node a
,node b
)
{return a
.x
<b
.x
;
}
int main(void)
{int st
,ed
; cin
>>st
>>ed
;int n
; cin
>>n
;for(int i
=0;i
<n
;i
++) cin
>>Node
[i
].x
>>Node
[i
].y
;sort(Node
,Node
+n
,cmp
);int res
=0;bool flag
=false;for(int i
=0;i
<n
;i
++){int j
=i
,r
=-1e9;while(j
<n
&&Node
[j
].x
<=st
){r
=max(r
,Node
[j
].y
);j
++;}if(r
<st
){res
=-1;break;}res
++;if(r
>=ed
){flag
=true;break;}st
=r
;i
=j
-1;}if(!flag
) cout
<<-1<<endl
;else cout
<<res
<<endl
;return 0;
}
#include<bits/stdc++.h>
using namespace std
;
vector
< pair
<int,int> > ve
;
int n
,l
,r
,st
,ed
;
int main(void)
{cin
>>st
>>ed
;cin
>>n
;while(n
--) cin
>>l
>>r
,ve
.push_back({l
,r
});sort(ve
.begin(),ve
.end());int ans
=0;for(int i
=0;i
<ve
.size();i
++){int j
=i
;bool flag
=false;int temp
=st
;while(j
<ve
.size()&&ve
[j
].first
<=temp
) flag
=true,st
=max(st
,ve
[j
++].second
);if(flag
) ans
++,i
=j
-1;if(st
>=ed
) {cout
<<ans
<<endl
;return 0;}}cout
<<-1<<endl
;return 0;
}
148. 合并果子
https://www.acwing.com/problem/content/description/150/
方法:每次選最小的兩個合并。
小根堆做法
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std
;
int main(void)
{priority_queue
<int, vector
<int>, greater
<int> >heap
;int n
; cin
>>n
;while(n
--){int x
; cin
>>x
;heap
.push(x
);}long long int res
=0;while(heap
.size()>1){int a
=heap
.top(); heap
.pop();int b
=heap
.top(); heap
.pop();res
+=a
+b
;heap
.push(a
+b
);}cout
<<res
<<endl
;return 0;
}
大根堆做法
#include<cstdio>
#include<queue>
#include<iostream>
using namespace std
;
int main(void)
{int n
; cin
>>n
;priority_queue
<int> heap
;while(n
--){int x
; cin
>>x
;heap
.push(-x
);}long long int res
=0;while(heap
.size()>1){int a
=heap
.top(); heap
.pop();int b
=heap
.top(); heap
.pop();res
+=(-a
-b
);heap
.push(-(-a
-b
));}cout
<<res
<<endl
;return 0;
}
913. 排隊打水
https://www.acwing.com/problem/content/description/915/
思路: 由于若把時間長的放在后面接水,那么就較少人等,所以排序+貪心即可。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
long long int a
[N
],s
[N
];
int main(void)
{int n
; cin
>>n
;for(int i
=1;i
<=n
;i
++) cin
>>a
[i
];sort(a
+1,a
+n
+1);long long int sum
=0;for(int i
=1;i
<=n
-1;i
++) s
[i
]=s
[i
-1]+a
[i
],sum
+=s
[i
];cout
<<sum
<<endl
;return 0;
}
104. 貨倉選址
https://www.acwing.com/problem/content/description/106/
選中間的位置最優
詳細的證明
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
int a
[N
],sum
;
int main(void)
{int n
; cin
>>n
;for(int i
=0;i
<n
;i
++) cin
>>a
[i
];sort(a
,a
+n
);int area
=a
[n
/2];for(int i
=0;i
<n
;i
++) sum
+=abs(area
-a
[i
]);cout
<<sum
<<endl
;return 0;
}
125. 耍雜技的牛
https://www.acwing.com/problem/content/description/127/
按其和從小到大排序
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=1e5+10;
struct student
{int w
,s
;
}stu
[N
];
bool cmp(student a
,student b
)
{return a
.w
+a
.s
<b
.w
+b
.s
;
}
int main(void)
{int n
;cin
>>n
;for(int i
=1;i
<=n
;i
++) cin
>>stu
[i
].w
>>stu
[i
].s
;sort(stu
+1,stu
+n
+1,cmp
);int ans
=-1e9;int res
=0;for(int i
=1;i
<=n
;i
++){ans
=max(ans
,res
-stu
[i
].s
);res
+=stu
[i
].w
;}cout
<<ans
<<endl
;return 0;
}
總結
以上是生活随笔為你收集整理的第六章 贪心 【完结】的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。