UVA - 1193(贪心.)、HDU - 1495(bfs.)、UVA - 10020(贪心求最少线段区间覆盖.)

Time limit 3000 ms
OS Linux

题目:
Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each
small island is a point locating in the sea side. And any radar installation, locating on the coasting,
can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance
between them is at most d.
We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above
x-axis, and the land side below. Given the position of each island in the sea, and given the distance of
the coverage of the radar installation, your task is to write a program to find the minimal number of
radar installations to cover all the islands. Note that the position of an island is represented by its x-y
coordinates.
Figure 1: A Sample Input of Radar Installation
Input
The input consists of several test cases. The first line of each case contains two integers n (1 ≤ n ≤ 1000)
and d, where n is the number of islands in the sea and d is the distance of coverage of the radar
installation. This is followed by n lines each containing two integers representing the coordinate of the
position of each island. Then a blank line follows to separate the cases.
The input is terminated by a line containing pair of zeros.
Output
For each test case output one line consisting of the test case number followed by the minimal number
of radar installations needed. ‘-1’ installation means no solution for that case.
Sample Input
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
Sample Output
Case 1: 2
Case 2: 1

代码:

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>//sort所在的库文件,排序用
using namespace std;
const int MAXN=1005;
struct Line
{
    double l,r;
}line[MAXN];//每个岛作半径为d的圆,与x轴所截的线段

bool cmp(Line a,Line b)
{
    
    return a.l<b.l;
}       //按照线段的左端点从小到大排序
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    int n,d;
    int i;
    int x,y;
    bool yes;//确定是不是有解
    int icase=1;
    while(cin>>n>>d)
    {
        yes=true;
        int cnt=0;
        if(n==0&&d==0)break;
        for(i=0;i<n;i++)
        {
            cin>>x>>y;
            if(yes==false)continue;
            if(y>d)yes=false;
            else
            {
                line[i].l=(double)x-sqrt((double)d*d-y*y);
                line[i].r=(double)x+sqrt((double)d*d-y*y);
            }    
        }
        if(yes==false)
        {
            cout<<"Case "<<icase++<<": -1"<<endl;
            continue;
        }
        sort(line,line+n,cmp);
        cnt++;
        double now=line[0].r;
        for(i=1;i<n;i++)
        {
            
            if(line[i].r<now)//这点很重要 
               now=line[i].r;
            else if(now<line[i].l)
            {
                now=line[i].r;
                cnt++;
            }    
        }
        cout<<"Case "<<icase++<<": "<<cnt<<endl;    
                
    }     
    return 0;
}

Time limit1000 ms
Memory limit32768 kB
OSWindows

题目:
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
Input
三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。
Output
如果能平分的话请输出最少要倒的次数,否则输出"NO"。
Sample Input
7 4 3
4 1 3
0 0 0
Sample Output
NO
3

代码:

#include <queue>
#include <cstring> //用来给数组赋初值为0的,memset;
using namespace std;
int b[3],book[101][101][101],half;
struct node
{
    int cur[3],s;          //cur表示现在瓶子里的水,b表示水的容量
}p,temp;          //p获取当前的“head”,temp用于6个动作的记录。
void bfs()
{
    queue<node> q;         //声明一个队列,由于经常做pat乙  只有一组数据习惯声明全局变量,如果把这句放在bfs()外边,因为有多组
    p.cur[0]=b[0];          //测试数据,如果不把之前队列里的数据清空就会带到下一组测试中(做题考虑下这个机制会不会对某些题目有用)
    p.cur[1]=p.cur[2]=p.s=0;  //放到bfs里面  每次队列都是新的。
    q.push(p);                  //将最开始状态初始化 加入队列q中;
    while(!q.empty())
    {
        p=q.front();
        q.pop();
        for(int i=0;i<3;i++)     //控制哪个杯子往外倒水
        {
            if(p.cur[i]>0)      //如果有水才可以给别的倒水。
            {
                for(int j=0;j<3;j++)   //接受水的杯子
                {
                    temp=p;            //这很重要!之前没加这句一直wa,因为这6个动作是”平行“的,即都是从前一步状态开始的,如果没有
                    if(i==j)  continue ;   //这一句,就不是平行的,相互叠加的。这个很重要!
                    if(temp.cur[i]>b[j]-temp.cur[j])   //判断能不能倒满了,这是可以倒满的情况
                    {
                        temp.cur[i]-=b[j]-temp.cur[j];      //这两句话一定不要颠倒,之前因为这个一直不出答案,先运算后赋值。。。
                        temp.cur[j]=b[j];
                    }
                    else     // 不可以倒满的情况
                    {
                        temp.cur[j]+=temp.cur[i];
                        temp.cur[i]=0;
                    }
                    if(!book[temp.cur[0]][temp.cur[1]][temp.cur[2]])  //判断这种情况是否出现过
                    {
                        book[temp.cur[0]][temp.cur[1]][temp.cur[2]]=1;  //标记为出现过,说明这一步“有效”,step+1;
                        temp.s++;
                        if((temp.cur[0]==half&&temp.cur[1]==half)||(temp.cur[0]==half&&temp.cur[2]==half)||(temp.cur[1]==half&&temp.cur[2]==half))
                            {
                                cout << temp.s << endl;  // step里的每一个“动作”都要判断是否符合条件,因为这动作是平行的 所以放在内循环里面!
                                return ;             //直接跳出bfs
                            }
                            q.push(temp);// 如果不是所求,就把他加到队列里。之后在从每一个“动作调用”
                    }
                }
            }
        }
 
 
    }
      cout <<"NO"<<endl;  //如果整个循环结束还是没有找到说明不可以平分;
}
int main()
{
    while(cin >> b[0]>>b[1]>>b[2],b[0]+b[1]+b[2])   //如果相加都等于0 即000 用于结束
    {
        memset(book,0,sizeof(book));  //多组数据每一组都要赋初值,想用book【】【】={0},必须要在声明book数组时候用;
        book[b[0]][b[1]][b[2]]=1;   //把初始点标记来过,这一点在调用bfs之前做 很多题都要注意这一点。
        if(b[0]%2)  cout << "NO"<<endl;
        else {half=b[0]/2;bfs();}
    }
    return 0;
}

Time limit 3000 ms
OS Linux

题目:
Given several segments of line (int the X axis) with coordinates [Li
, Ri
]. You are to choose the minimal
amount of them, such they would completely cover the segment [0, M].
Input
The first line is the number of test cases, followed by a blank line.
Each test case in the input should contains an integer M (1 ≤ M ≤ 5000), followed by pairs “Li Ri”
(|Li
|, |Ri
| ≤ 50000, i ≤ 100000), each on a separate line. Each test case of input is terminated by pair
‘0 0’.
Each test case will be separated by a single line.
Output
For each test case, in the first line of output your programm should print the minimal number of line
segments which can cover segment [0, M]. In the following lines, the coordinates of segments, sorted
by their left end (Li), should be printed in the same format as in the input. Pair ‘0 0’ should not be
printed. If [0, M] can not be covered by given line segments, your programm should print ‘0’ (without
quotes).
Print a blank line between the outputs for two consecutive test cases.
Sample Input
2
1
-1 0
-5 -3
2 5
0 0
1
-1 0
0 1
0 0
Sample Output
0
1
0 1

代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
struct node
{
 int x,y;
}a[100001],b[100001];
int cmp(node a,node b)
{
 return a.x<b.x;
}
int main()
{
 int max,pos,i,begin,end,m,n,sum,f,posmax,t;
 scanf("%d",&t);
 while (t--) 
 {
 scanf("%d",&m);
 n=0;
 while (scanf("%d%d",&begin,&end))
 {
  if (begin==0&&end==0) break;
  if (end>=0)
  {
   a[n].x=begin;
   a[n].y=end;
   ++n;
  }
 }
 sort(a,a+n,cmp);
 if (a[0].x>0) printf("0\n");//开始漏了没判断第一条线段就不能覆盖到0,wrongY-Y;
 else
 {
 pos=0; max=0; sum=1;
 while (pos+1<n&&a[pos+1].x<=0)//pos+1<N防止数组越界,还真有所有数据都从小于0开始的,re Y-Y;
 {
  ++pos;
  if (a[pos].y>a[max].y) max=pos;
 }
 pos=max; b[1].x=a[pos].x; b[1].y=a[pos].y;
 while (pos<n && b[sum].y<m) 
 {
  f=1; posmax=max;
  while (pos+1<n && a[pos+1].x<=a[max].y)
  {
  f=0;
   ++pos;
   if (a[pos].y>a[posmax].y) posmax=pos;
  }
  if (f) break;
  max=posmax;
  ++sum;
  b[sum].x=a[max].x;
  b[sum].y=a[max].y;
 }
 if (b[sum].y>=m) 
 {
  printf("%d\n",sum);
  for (i=1;i<=sum;i++)
  printf("%d %d\n",b[i].x,b[i].y);
 }else printf("0\n");
 }
 if (t) printf("\n");
 }
 return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43967023/article/details/86684438
今日推荐