Loading

贪心算法

#10000. 「一本通 1.1 例 1」活动安排

思想

贪心

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int M = 1010;
typedef long long ll;
int read(){
   int x = 0,f = 1;char c = getchar();
   while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
   while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
   return f*x;
}
struct node{
   int l,r;
}a[M];
bool cmp(node a,node b){
   return a.r < b.r;
}
int ans,nr;
int main()
{
  int  n = read();
  for (int i = 1;i <= n; i++){
  	  a[i].l = read();
      a[i].r = read();
  }
  sort (a + 1, a + n + 1, cmp);
  for (int i = 1;i <= n; i++){
  	 if(a[i].l >= nr){
  	     ans++,nr = a[i].r;  	
     }
  }
  printf("%d\n",ans);
  return 0;
}

10001. 「一本通 1.1 例 2」种树

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 3e4 + 10;
typedef long long ll;
int read() {
    int x = 0, f = 1;
    char c = getchar();

    while (c < '0' || c > '9') {
        if (c == '-')
            f = -1;

        c = getchar();
    }

    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar();
    }

    return f * x;
}
int n, t, mp[M], s, ans;
struct Query {
    int l, r, num;
} q[M];
bool cmp(Query a, Query b) {
    return a.r < b.r;
}
int main() {
    n = read(), t = read();

    for (int i = 1; i <= t; i++) {
        q[i].l = read();
        q[i].r = read();
        q[i].num = read();
    }

    sort(q + 1, q + t + 1, cmp);

    for (int i = 1; i <= t; i++) {
        int cnt = q[i].r;
        int js = 0;

        for (int j = q[i].l; j <= q[i].r; j++) {
            js += mp[j];
        }

        if (js >= q[i].num)
            continue;

        for (int k = q[i].r; k >= q[i].l; k--) {
            if (!mp[k]) {
                js++;
                ans++;
                mp[k] = 1;

                if (js == q[i].num)
                    break;
            }
        }
    }

    printf("%d", ans);
    return 0;
}

10002. 「一本通 1.1 例 3」喷水装置

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 15010;
typedef long long ll;
int read(){
   int x = 0,f = 1;char c = getchar();
   while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
   while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
   return f*x;
}
int n,l,w;
struct node{
	double l,r;
}a[M];
int main()
{	
  int t = read();
  while (t--){
  	int cnt = 0;
  	n = read(),l = read(),w = read();
  	
  	memset(a, 0, sizeof(a));
  	
  	for (int i = 1;i <= n; i++){
  		 int pos = read(),r = read();
  		 if(r * 2 <= w) continue;
  		 
  		 double len = sqrt(r * r - w * w / 4.0);
  		 
		 a[++cnt].l = (pos - len) * 1.0;
		 a[cnt].r = (pos + len) * 1.0;
	 }
	
	int ans = 0,flag = 0;
	double now = 0;
	while(now < l){
	    ans++;
		double s = now;
		for(int i = 1;i <= cnt; i++){
			if(a[i].l <= s && a[i].r > now){
				 now = a[i].r;
			}
		}
		if(now == s && s < l){
			printf("-1\n");
			flag = 1;
			break;
		}
 	 }
	 if(!flag) printf("%d\n",ans);
  }

  return 0;
}

10003. 「一本通 1.1 例 4」加工生产调度

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 1e4 + 4;
typedef long long ll;
int read(){
   int x = 0,f = 1;char c = getchar();
   while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
   while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
   return f*x;
}
struct node{
	int a,b,num;
}work[M];
int ans;
bool cmp(node x,node y){
    return min(x.a , y.b) < min(y.a , x.b);
}
int tima,timb;
int main()
{
  int n = read();
  for(int i = 1;i <= n; i++){
  	 work[i].a = read();
  	 work[i].num = i;
  }
  for(int i = 1;i <= n; i++){
  	 work[i].b = read();
  }
  sort(work + 1, work + n + 1, cmp);
  for(int i = 1;i <= n; i++){
  	 tima += work[i].a;
  	 timb = max(tima, timb) + work[i].b;
  }
    cout << timb <<"\n";
    for (int i = 1; i < n; i++) {
        cout << work[i].num << " ";
    }
    cout << work[n].num;
  return 0;
}

智力大冲浪

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;
const int M = 510;
typedef long long ll;
int read(){
   int x = 0,f = 1;char c = getchar();
   while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
   while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
   return f*x;
}
int n,m,sum,minn,num,pos;
struct Game{
   int tim,cos;
}g[M];
bool cmp(Game a,Game b){
	if(a.tim == b.tim) return a.cos < b.cos;
	return a.tim < b.tim;
}
void work(){
	int cnt = 0;
	for(int i = 1;i <= n; i++){
	   	 cnt++;
	   while(cnt > g[i].tim){
	   	   cnt--;minn = inf;
	   	  for (int j = 1;j <= i; j++){
	   	  	   if(g[j].cos !=0 && g[j].cos < minn){
	   	  	      minn = g[j].cos;pos = j;
			   }
		   }
		   g[pos].cos = 0;
		   sum += minn;
	    }
	}
}
int main()
{
  m = read(), n = read();
  for(int i = 1;i <= n; i++){
  	   g[i].tim = read();
  }
   for(int i = 1;i <= n; i++){
  	   g[i].cos = read();
  }
  sort(g + 1,g + n + 1, cmp);
  work();
  printf("%d",m - sum);
}

10005. 「一本通 1.1 练习 1」数列极差

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 5e4 + 5;
typedef long long ll;
int read(){
   int x = 0,f = 1;char c = getchar();
   while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
   while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
   return f*x;
}
int n,a[M],b[M],zz;
int main()
{
  n =  read();
  for(int i = 1;i <= n; i++) a[i] = read(),b[i] = a[i];
  sort(a + 1,a + n + 1);
  sort(b + 1,b + n + 1);
  for(int i = 2;i <= n + 1; i++){
  	   a[i] = a[i - 1]*a[i] + 1;
	   sort(a + 1,a + n + 1);
  }
  for(int i = n - 1;i >= 1; i--){
  	   b[i] = b[i + 1]*b[i] + 1;
  }
  cout<<a[n]-b[1]<<"\n";
  return 0;
}

10006. 「一本通 1.1 练习 2」数列分段

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 1e5 + 5;
typedef long long ll;
int read(){
   int x = 0,f = 1;char c = getchar();
   while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
   while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
   return f*x;
}
int n,m,a[M],ans,cnt;
int main()
{
  n = read(),m = read();
  for (int i = 1;i <= n; i++){
  	  a[i] = read();
  }
  for(int i = 1;i <= n; i++){
  	  cnt += a[i];
  	  if(cnt == m){
  	  	  ans++;
  	  	   cnt = 0;
  	  	   if(i == n) break;	
		}
	  if(cnt > m){
	  	  cnt = a[i];
	  	  ans++;
	  	  if(i == n) break;
	  }
	  if(i == n && cnt < m){
	  	  ans++;
	  }
  }
  printf("%d",ans);
  return 0;
}

10007. 「一本通 1.1 练习 3」线段

/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 1e6 + 5;
typedef long long ll;
int read(){
   int x = 0,f = 1;char c = getchar();
   while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
   while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
   return f*x;
}
int n,ans = 1,last = 1;
struct node{
	int l,r;
}a[M];
bool cmp(node a,node b){
	return a.r < b.r;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
}
int main()
{
  n = read();
  for(int i = 1;i <= n; i++){
  	 a[i].l = read();
	 a[i].r = read();
  }
  sort(a + 1,a + n + 1,cmp);
  
  for(int i = 2;i <= n; i++){
  	  if(a[i].l >= a[last].r){
  	     last = i;
		 ans++; 	
	 }
  }
  cout<<ans;
  return 0;
}

10008. 「一本通 1.1 练习 4」家庭作业

思想:

按分数从大到小排序,绕后找按时间从小到大做作业;

实现:

枚举这个作业的时间,看他这个时间之前的时间(包括这个时间)有没有被占用过

如果时间全占用过个这个作业不合法,继续枚举下一个

如果还有时间没被占用过,就贪心枚举离这个时间最近的没有用过的时间来做这个作业

/*
work by:Ariel_
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
//==========================
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){
	if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&& c <= '9'){x = x*10 + c - '0',c = getchar();}
	return x*f;
}
//===============================================================
struct node{
   int tim,sore;
}a[D];
bool cmp(node a,node b){
	if(a.sore == b.sore) return a.tim > b.tim;
	return a.sore > b.sore;
}
int n,ans,now,vis[D];
int main(){
   n = read();
   for (int i = 1;i <= n; i++){
   	    a[i].tim = read();
   	    a[i].sore = read();
   }
   sort(a + 1,a + n + 1,cmp);
   for(int i = 1;i <= n; i++){
   	   if(a[i].tim <= now) continue;
   	   int f = 0;
   	   for(int j = a[i].tim;j >= 1; j--){
   	   	      if(!vis[j]){
   	   	          vis[j] = 1;
				  f = 1;
				  ans += a[i].sore;	
				  break;
			  } 
		}
	   if(!f) now = a[i].tim;
   }
   printf("%d",ans);
}

#10009. 「一本通 1.1 练习 5」钓鱼

思想

优先队列,贪心

/*
work by:Ariel_
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
//==========================
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){
	if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&& c <= '9'){x = x*10 + c - '0',c = getchar();}
	return x*f;
}
//===============================================================
struct node{
   int f,num;
   bool operator <	(node x)const {
       return f < x.f;
   }
   	
}a[B];
priority_queue<node>q;
int n,h,d[B],t[B],ans;
int main(){
    
   n = read(),h = read();
   h *= 12;//都是以五分钟为单位,所以这里进行个特殊处理
   for (int i = 1;i <= n; i++){
   	   a[i].f = read();
   	   a[i].num = i;
   }
   for (int i = 1;i <= n; i++){
   	    d[i] = read();
   }
   for (int i = 1;i < n; i++){
   	    t[i] = read();
   }
   for (int i = 1;i <= n; i++){
   	    h -= t[i-1];
   	    while(!q.empty())q.pop();
   	    for(int j = 1;j <= i; j++){
   	         q.push(a[j]); 	
		 }
		 int now = 0;
		for(int j = 1;j <= h; j++){
			 node s;
			 s = q.top();
			 if(s.f > 0)now += s.f;
			 s.f -= d[s.num];
			 q.pop();
			 q.push(s); 
		}
		ans = max(now,ans);
   }
   printf("%d",ans);
}

10010. 「一本通 1.1 练习 6」糖果传递

思想:

均分纸牌思想,贪心

/*
work by:Ariel_
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
typedef long long ll;
//==========================
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){
	if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&& c <= '9'){x = x*10 + c - '0',c = getchar();}
	return x*f;
}
//===============================================================
int n,a[D],sum,res,ans,f[D];
signed main(){
    n = read();
    for(int i = 1;i <= n; i++){
        a[i] = read();	
        sum += a[i];
	}
    res = sum/n;
    for(int i = 1;i <= n; i++){
    	f[i] = f[i - 1] + a[i] - res;
	}
	sort(f + 1,f + n + 1);
	for(int i = 1;i <= n; i++)ans += abs(f[i] - f[(n >> 1) + 1]);
	printf("%lld",ans);
}

10011. 「一本通 1.2 例 1」愤怒的牛

思想

二分板子

/*
work by:Ariel_
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#define orz cout<<"Ak ioi"<<endl;
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
//==========================
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){
	if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&& c <= '9'){x = x*10 + c - '0',c = getchar();}
	return x*f;
}
//===============================================================
int n,m,a[C],maxn,ans,zz,l = 1,r;
bool juge(int x){
	int js = 1,last = 1;
    for(int i = 2;i <= n; i++){
         if(a[i] - a[last] >= x){
         	 js++;last = i;
		 } 
	}
	if(js >= m) return true; 
	else
	return false;
}
void mid_search(){
	r = a[n] - a[1];
	while(l <= r){
		int mid = (l + r)>>1;
		if(juge(mid)) l = mid + 1;
		else r = mid - 1;
	}
}
int main(){
   n = read(),m = read();
   for(int i = 1;i <= n; i++){
   	   a[i] = read();
   }
   sort(a + 1,a + n + 1);
   mid_search();
   printf("%d",l - 1);
}

10012. 「一本通 1.2 例 2」Best Cow Fences

思想
/*
work by:Ariel_
*/
/*mind:
   枚举平均值,然后将每数都减去平均值
   判断区间是否符合大于等于平均值 
*/ 
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
#define int long long
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
//==========================
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){
	if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&& c <= '9'){x = x*10 + c - '0',c = getchar();}
	return x*f;
}
//===============================================================
int n,l,a[C],max_,b[C];
bool cheak(int x){
	int minn = inf;
	for(int i = 1;i <= n; i++){
		 b[i] = a[i] + b[i - 1]- x;
		 if(i >= l){
		   minn = min(minn,b[i - l]);
		   if(b[i] > minn)
		   return true;
		 }
	}
	return false;
}
signed main(){
   n = read(),l = read();
   for (int i = 1;i <= n; i++){
   	   a[i] = read();
   	   a[i] =a[i]*10000;
	   max_ = max(max_,a[i]);
   }
   int l = 1,r = max_;
   while(l <= r){
   	  int mid = (l + r)>>1;
   	  if(cheak(mid)) l = mid + 1;
   	  else r = mid - 1;
   }
   printf("%d",l/10);
}

10013. 「一本通 1.2 例 3」曲线

思想:

三分

/*
work by:Ariel_
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
//==========================
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
const double jd = 1e-9;
//===============================================================
int T, n, a[C], b[C], c[C];
double check(double x) {
    double maxn_ = 0;

    for (int i = 1; i <= n; i++)
        maxn_ = max(maxn_, a[i] * x * x * 1.0 + b[i] * x * 1.0 + c[i] * 1.0);

    return maxn_;
}

int main() {
    scanf("%d", &T);

    while (T--) {
        scanf("%d", &n);

        for (int i = 1; i <= n; i++) {
            scanf("%d %d %d", &a[i], &b[i], &c[i]);
        }

        double l = 0, r = 1000;

        while (r - l > jd) {
            double mid1, mid2;
            mid1 = l + (r - l) / 3.0;
            mid2 = r - (r - l) / 3.0;;

            if (check(mid1) < check(mid2))
                r = mid2;
            else
                l = mid1;
        }

        printf("%.4lf\n", check(l));
    }

}

10014. 「一本通 1.2 练习 1」数列分段 II

思想:

二分板子,注意边界处理

/*
work by:Ariel_
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
//==========================
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){
	if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&& c <= '9'){x = x*10 + c - '0',c = getchar();}
	return x*f;
}
//===============================================================
int n,m,a[C],maxn_,l,r,ans;;
bool check(int x){
    int sum = 0,tot = 1;
    for(int i = 1;i <= n; i++){
         if(sum + a[i] > x){
         	 sum = 0;
         	 tot++;
		 }
		 sum += a[i];
	}
	return tot <= m;
}
int main(){
   n = read(), m = read();
   
   for(int i = 1;i <= n; i++){
   	    a[i] = read();
   	    r += a[i];
   	    l = max(l,a[i]);
   }
   while(l <= r){
   	  int mid = (l + r)>>1;
   	  if(check(mid)){
   	  	 r = mid - 1;
   	  	 ans = mid;
	   }
   	  else l = mid + 1;
   }
   printf("%d",ans);
}

10015. 「一本通 1.2 练习 2」扩散

思想

图论,判断图是否联通:最近公共祖先,并查集

二分枚举时间

/*
work by:Ariel_
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
//==========================
const int A = 1e9;
const int B = 1e4 + 2;
const int C = 1e5 + 2;
const int D = 1e6 + 2;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){
	if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&& c <= '9'){x = x*10 + c - '0',c = getchar();}
	return x*f;
}
//===============================================================
int fa[55];
int find(int x){
   return (fa[x] == x) ? fa[x]:fa[x] = find(fa[x]);
}
struct node{
	int xx,yy;
}a[55];
int n;
int main(){
   n = read();
   for(int i = 1;i <= n; i++){
   	    a[i].xx = read();
   	    a[i].yy = read();
   }
   int l = 0,r = A,ans = 0;
   while(l <= r){
   	   int mid = (l + r) >> 1;
   	   for(int i = 1;i <= n; i++) fa[i] = i;//初始化
	   for (int i = 1;i <= n; i++){//两两枚举点看是否能在规定时间联通 
	   	  for (int j = i + 1;j <= n; j++){
	   	  	     int dis = abs(a[j].xx - a[i].xx) + abs(a[j].yy - a[i].yy);//曼哈顿距离
	   	  	     if(dis <= mid * 2){//因为是两个点,所以扩散速度应该为两倍
				     int fa1 = find(i);
					 int fa2 = find(j);
					 if(fa1 != fa2) fa[fa1] = fa2;//把两个点连起来 
				  }  
			 }	 
	   }
	   int cnt = 0;
	   for(int i = 1;i <= n; i++){
	   	   if(fa[i] == i){
	   	      cnt++;	
		   } 
	   }
	   if(cnt == 1){//图能联通 
	   	 ans = mid;
		 r = mid - 1;  
	   }
	   else {
	   	  l = mid + 1;
	   } 
   }
   printf("%d",ans); 
}

posted @ 2020-12-20 22:17  Dita  阅读(62)  评论(0编辑  收藏  举报