貪心法(洛谷普及場1)
阿新 • • 發佈:2018-12-17
#include<bits/stdc++.h>
#define fo(i,j,n) for(register int i=j;i<=n;++i)
#define ll long long
using namespace std;
priority_queue<int, vector<int>, greater<int>> pq;
int n,a,b;
int main(){
scanf("%d",&n);
fo(i,1,n){
scanf("%d",&a);
pq.push(a);
}
ll ans = 0;
fo (i,1,n-1){
a=pq.top();pq.pop();
b=pq.top();pq.pop();
ans += a+b;
pq.push(a+b);
}
printf("%lld\n", ans);
return 0;
}
P1181 數列分段Section I 題目連結:https://www.luogu.org/problemnew/show/P1181 解法一:從左到右倍增直到區間不能再增大為止 解法二:貪心,從左到右一直加到不滿足為止,然後重新加
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int maxn = 1e5+5;
int n,m,a[maxn],sum[maxn];
void solve(){
int l=1,p=1,r=l,ans=0;
while(l<=n){
ans++;
r=l,p=1;
while(p){
if(r+p>n){
p >>= 1;continue;
}
if(sum[r+p]-sum[l-1]<=m){
r += p;
p <<= 1;
}else{
p >>= 1;
}
}
l = r+1;
// cout<<r<<endl;
}
printf("%d\n",ans);
}
void solve1(){
int ans=1,s=0,x;
fo(i,1,n){
scanf("%d",&x);
if(s+x<=m){
s+=x;
}else{
ans++;
s=x;
}
}
printf("%d\n",ans);
}
int main(){
scanf("%d%d",&n,&m);
// fo(i,1,n)scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
// solve(); // 倍增法,複習一下
solve1();// 直接倍增
return 0;
}
#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n,m;
vector<pair<int,int> > ver;
void solve(){
sort(ver.begin(),ver.end());
ll ans=0,all=0;
for(auto p:ver){
if(all+p.second<=n){
ans += p.first*p.second;
all += p.second;
}else{
ans += (n-all)*p.first;
break;
}
}
printf("%lld\n",ans);
}
int main(){
scanf("%d%d",&n,&m);
int a,b;
fo(i,1,m){
scanf("%d%d",&a,&b);
ver.push_back(mk(a,b));
}
solve();
return 0;
}
P1223 排隊接水 題目連結:https://www.luogu.org/problemnew/show/P1223 題解: 微擾法證明: 要使總等待時間最少,每一次接水的是還沒接水的人中(m人)接水時間t1最少的 這時的後面的人的總等待時間為(m-1)t1,由於ti最小,則該局面下的總等待時間最小 設後面的某個人的等待時間為tk(tk>t1),排第k位(k>1) 這後面的人等待該人的總等待時間為 tk(m-k) 等待 這兩個人的總等待時間為 (m-1)t1+(m-k)tk = m(t1+tk) - t1-ktk = T1 若交換兩人位置,等待兩人的總等待時間為 (m-1)tk+(m-k)t1 = m(t1+tk) - tk-kt1 = Tk TK-T1 = -tk - kt1 + t1 + ktk = (k-1)*tk - (k-1)t1 = (k-1)(tk-t1)>0 所以任意非位置一(接水時間最少)的位置k,與位置一交換都會使得總等待時間變長 證畢。
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
#define mk make_pair
using namespace std;
int n;
vector<pair<int,int> > ver;
int main(){
scanf("%d",&n);
int x;
fo(i,1,n){
scanf("%d",&x);
ver.push_back(mk(x,i));
}
sort(ver.begin(),ver.end());//當ti重複時,按照輸入順序即可(sort是可以的)
double sum=0.0,all=0.0;
fo(i,0,n-1){
all+=sum; // 加上ver[i].second,這位同學的等待時間
sum+=ver[i].first;// 計算下一位同學的等待時間
printf("%d%c",ver[i].second,i==n-1?'\n':' ');
}
printf("%.2f\n",all/n);
return 0;
}
#include<bits/stdc++.h>
#define fo(i,j,n) for(register int i=j; i<=n;++i)
using namespace std;
int m,n,a[30005];
int main(){
scanf("%d%d",&m,&n);
fo(i,1,n)scanf("%d",&a[i]);
sort(a+1,a+1+n);
int ans=0,l=1,r=n;
while(l<=r){
if(a[r]+a[l]<=m){
r--;l++;
ans++;
}else{
r--; ans++;
}
}
printf("%d\n",ans);
}
P1803 凌亂的yyy / 線段覆蓋 題目連結:https://www.luogu.org/problemnew/show/P1803 解法:右端點進行排序,每次選擇右端點儘量小的,如果該區間可以選擇的話,否則繼續選擇其他右端點儘量小的
#include<bits/stdc++.h>
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
#define mk make_pair
using namespace std;
int n;
vector<pair<int,int> > ver;
int main(){
scanf("%d",&n);
int a,b;
fo(i,1,n)scanf("%d%d",&a,&b),ver.push_back(mk(b,a));
sort(ver.begin(),ver.end());
int ans = 0,last=0;
fo(i,0,n-1){
if(ver[i].second>=last){
last=ver[i].first;
ans++;
}
}
printf("%d\n",ans);
return 0;
}