贪心组题

Schedule

HDU 6180
每个任务有一个开始时间和结束时间,每台机器同一时刻只能做一个任务,求最少可以完成任务的机器数量。
经典的任务调度,将开始时间与结束时间同时排序,每开始/结束一个任务,当前任务数sum++/–,最少机器数即为过程中sum的最大值。
因为只要求总时间,不要求一一对应,所以只需求出rili\sum r_i-\sum l_i即可。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define ll long long
using namespace std;
const int N = 1e6+10;
typedef std::pair<int, int> pii;
pii a[2 * N];
int l[N], r[N];

int main(){
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            int s, e;
            scanf("%d%d", &s, &e);
            a[2 * i - 1] = pii(s, 1);
            a[2 * i] = pii(e, -1);
        }
        sort(a + 1, a + 2 * n + 1);
        memset(l, -1, sizeof(l));
        memset(r, -1, sizeof(r));
        int sum = 0, ans = 0;
        for (int i = 1; i <= 2 * n; i++)
        {
            if (a[i].second == 1){
                sum++;
                if (l[sum] == -1) l[sum] = r[sum] = a[i].first;
                ans = max(ans, sum);
            }
            else
            {
                r[sum] = a[i].first;
                sum--;
            }
        }
        ll time = 0;
        for (int i = 1; i <= ans; i++) time += 1ll*(r[i] - l[i]);
        printf("%d %lld\n", ans, time);
    }
    return 0;
}

Gene Assembly

ZOJ 1076
nn个区间,求最多数量的不相交区间。
经典的区间调度,将右边界排序,顺序取即可。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define ll long long
using namespace std;
const int N = 1e3+10;
typedef std::pair<int, int> pii;
struct node{
    int l,r;
    int id;
}a[N];
int n;
bool cmp(node a,node b){
    if(a.r==b.r) return a.l>b.l;
    else return a.r<b.r;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    while(cin>>n && n)
    {
        for(int i=0;i<n;i++)
            cin>>a[i].l>>a[i].r,a[i].id=i+1;
        sort(a,a+n,cmp);
        printf("%d",a[0].id);
        int last=0;
        for(int i=1;i<n;i++)
            if (a[i].l > a[last].r){
                printf(" %d", a[i].id);
                last = i;
            }
        printf("\n");
    }
    return 0;
}   

Pass-Muraille

POJ 1230
在一个网格上水平的有很多线段,对于每一列,从上到下最多只能穿过k个线段,求最少删去多少个线段。
很容易想到,某一列线段超过k个线段时,优先删除的肯定是线段右边界距当前列最远的,因为这样就可以使删除对后续答案影响最大。
upd:这题在poj上用cin总是wa,最后用了scanf才过。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define ll long long
using namespace std;
const int N = 1e2+10;
typedef std::pair<int, int> pii;
int mtx[N][N];
int n,k;
struct node{
    int x0,x1,y;
}a[N];
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int xn=0,yn=0,ans=0;
        memset(mtx,0,sizeof mtx);
        scanf("%d%d",&n,&k);
        for(int i=0;i<n;i++) {
            scanf("%d%d%d%d", &a[i].x0, &a[i].y, &a[i].x1, &a[i].y);
            if (a[i].x0 > a[i].x1) swap(a[i].x0, a[i].x1);//填数据的坑
            xn=max(xn,a[i].x1);
            yn=max(yn,a[i].y);
            for(int j=a[i].x0;j<=a[i].x1;j++) mtx[a[i].y][j]=a[i].x1;
        }
        for(int i=0;i<=xn;i++)
        {
            int d=0;
            for(int j=0;j<=yn;j++)
                if(mtx[j][i]) d++;
            while(d>k)
            {
                int maxl=0,pos=0;
                for(int j=0;j<=yn;j++)
                    if(mtx[j][i] > maxl)
                    {
                        maxl=mtx[j][i];
                        pos=j;
                    }
                int posi=mtx[pos][i];
                for(int j=i;j<=posi;j++)
                    mtx[pos][j]=0;
                d--;
                ans++;
            }/*
            for(int i=0;i<=m;i++)
            {
                for(int j=0;j<=m;j++) cout<<mtx[i][j]<<' ';cout<<endl;
            }cout<<endl;*/
        }
        cout<<ans<<endl;
    }
    return 0;
}

Radar Installation

POJ 1328
求最少几个圆可以覆盖所有的点。
每个点的可覆盖圆圆心都在一个区间内,转化后问题变为数轴上最少取几个点可以被所有区间覆盖。
排序左边界后贪心。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define ll long long
using namespace std;
const int N = 1e5+10;
typedef std::pair<int, int> pii;
struct node{
    double l,r;
    bool operator<(const node&rhs)const{
        return l<rhs.l;
    }
}a[N];
int n;
double d;
bool cmp(node a,node b){
    return a.l<b.l;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int iCase=0;
    while(cin>>n>>d &&n)
    {
        iCase++;
        int x,y,flag=1;
        for(int i=0;i<n;i++){
            cin>>x>>y;
            if(y>d) flag=0;//!如果在这里直接break则会影响读入,多组数据下会报错
            if(flag) {
                a[i].l = (double) x - sqrt(d * d - y * y);
                a[i].r = (double) x + sqrt(d * d - y * y);
            }
        }
        if(!flag) {
            printf("Case %d: %d\n",iCase,-1);
            continue;
        }
        sort(a,a+n);
        int ans=1,last=0;
        for(int i=1;i<n;i++) {
            if (a[i].l > a[last].r) {
                last = i;
                ans++;
            } else if(a[i].r < a[last].r) last=i;//一定要把last更新为r最小的那个线段
        }
        printf("Case %d: %d\n",iCase,ans);
    }
    return 0;
}

Wooden Sticks

HDU 1065
一个木棍有重量w和长度l,当一个木棍重量和长度都比另一个木棍小时,就可以不用加工。求最少的加工时长。
问题也就是求最少的w和l都满足递增的序列。
贪心,将w排序,然后递增的找l。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define ll long long
using namespace std;
const int N = 1e4+10;
typedef std::pair<int, int> pii;
struct node{
    int w,l;
}a[N];
int n;
double m;
bool cmp(node a,node b){
    if(a.w==b.w) return a.l<b.l;
    else return a.w<b.w;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) {
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i].w >> a[i].l;
        sort(a + 1, a + n + 1, cmp);
        int vis[N] = {0}, ans = 0;
        for (int i = 1; i <= n; i++) {
            if (vis[i]) continue;
            int maxl = a[i].l;
            for (int j = i + 1; j <= n; j++) {
                if (!vis[j] && maxl <= a[j].l) {
                    vis[j] = 1;
                    maxl = a[j].l;
                }
            }
            ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}

Tian Ji – The Horse Racing

POJ 2287
田忌赛马

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define ll long long
using namespace std;
const int N = 1e3+10;
typedef std::pair<int, int> pii;
int n,a[N],b[N];
double d;
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    while(cin>>n &&n)
    {
        for(int i=0;i<n;i++) cin>>a[i];
        for(int i=0;i<n;i++) cin>>b[i];
        sort(a,a+n);//tian
        sort(b,b+n);//king
        int i,j,k,l,win=0,cnt=0;
        i=j=0;//slow
        k=l=n-1;//fast
        while(cnt<n)
        {
            if(a[k]>b[l]){//田忌快?更快
                ++win;
                k--;l--;
                ++cnt;
            }
            else if(a[k]<b[l]){//田忌快马比king快马慢,用最慢的马去输
                --win;
                i++;l--;
                ++cnt;
            }
            else{
                if(a[i]>b[j]){//田忌慢?比king慢马快
                    ++win;
                    i++;j++;
                    ++cnt;
                }else if(a[i]<b[l]){//尝试用慢马去赛king最快的马
                    --win;
                    i++;l--;
                    ++cnt;
                }else {
                    i++;l--;
                    ++cnt;
                }
            }
        }
        cout<<200*win<<endl;
    }
    return 0;
}
posted @ 2019-08-01 20:00  Mr.doublerun  阅读(20)  评论(0)    收藏  举报