USACO section1.3 Barn Repair 修理牛棚(贪心)

题目:http://www.wzoi.org/usaco/11%5C304.asp

 

大意:有m个点,用有数量限制的区间把这些点全部覆盖,求区间和的最小值。

 

贪心原理:如果限制的区间数大于等于m的话ans=m(就因为没考虑这点提交了好多次- -|||);否则,先用把点都排序(这里也忘记了- -|||),用标记法记录相邻点的距离,a[i]表示距离为i的个数。。。

每减少一次区间的个数相当于2个区间合并成一个区间,合并的话肯定选距离最小的那个。。。。。把区间个数减到限制的个数为止。。。。。。

 

/*
ID: qiufeih1
PROG: barn1
LANG: C++
*/

#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>
using namespace std;

const int INF = 1<<30;

int a[250];
int num[250];

int main()
{
freopen("barn1.in", "r", stdin);
freopen("barn1.out", "w",stdout);
int n, m;
int star, end;
int i, j;
int ans;
int count;
int flag;
int min, max;
int max_num;
scanf("%d%d%d", &max_num, &n, &m);
memset(a, 0, sizeof(a));

for (i = 0; i < m; i++)
{
scanf("%d", num+i);

}

ans = m;
if (max_num < m)//别漏
{
max_num = m - max_num;

sort(num, num+m);//别漏排序
for (i = 1; i < m; i++)
{
a[num[i]-num[i-1]-1]++;//标记距离的个数
}

i = 0;//距离从小到大取。。贪心
while (max_num--)
{
if (a[i])//存在距离为i
{
ans += i;
a[i]--;
}
else
{
while (!a[++i]);
ans += i;
a[i]--;
}
}
}

printf("%d\n", ans);

return 0;
}



你可能感兴趣的:(USACO)