一度掌握一干净长为L的细棍被加热了n摄氏度。分别表示你要的N+1种植颜色的毫升数。

【SInGuLaRiTy-1025】
Copyrights (c) SinGuLaRiTy 2017. All Rights Reserved.

【SinGuLaRiTy-1024】
Copyright (c) SinGuLaRiTy 2017. All Rights Reserved.

[POJ 1905] 棍的涨 (Expanding Rods)

[POJ 2709] 颜料 (Painter)

问题叙述

早就解一彻底长为L的细棍被烧了n摄氏度,那么该新的尺寸为L’=(1+n*C)*L。中间的C是热膨胀系数。
当一完完全全细棍被夹在片当墙壁中然后被温,它会胀,其相会成为一个弧,而原本的细棍(加热前之细棍)就是此弧所对的弦。
你的职责是测算出弧的中间与弦的中间的离开。

图片 1

问题叙述

百货公司出售一栽由N(3<=N<=12)种不同颜色之颜料,每种同等瓶(50ML),组成的水彩套装。你本要采用即时N种颜料;不但如此,你还用肯定数额之灰色颜料。杂货店从来不出售灰色颜料——也就是她不属即N种之一。幸运的是,灰色颜料是于好布局的,如果你取出三种不同颜色之水彩各x ml,混合起来便可博x ml的灰色颜料(注意勿是3x)。

今昔,你了解每种颜料各得多少ml。你控制买尽可能少的“颜料套装”,来满足你要之即N+1种颜色。那么你顶少得购置小个套装呢?

输入

蕴含多组数(每组占一行)。每一样执包含三单非负数:细棍的长度,温度的变化值和细棍材料的热膨胀系数C。输入数据保证细棍不会见暴涨超过自己之一半。
输入数据因三只连的-1最后。

输入

输入包含若干组测试数据。每组数据一行:第一个数N,
3<=N<=12, 含义如齐;接下去N+1单数,分别代表若要之N+1栽颜色的毫升数。最后一种植是灰色。所有输入的毫升数<=1000.

专注:输入被未在每个颜料套装的毫升数。由题意可知,每种各50ml,即总计50N ml。

输出

对各级一样组数,输出计算的离,答案保留三各类小数。

输出

对各级一样组数,输出一个整数,表示无比少套数。

样例数据

样例输入 样例输出
1000 100 0.0001
15000 10 0.00006
10 0 0.001
-1 -1 -1
61.329
225.020
0.000

 

 

 

 

 

样例数据

样例输入 样例输出
3 40 95 21 0
7 25 60 400 250 0 60 0 500
4 90 95 75 95 10
4 90 95 75 95 11
5 0 0 0 0 0 333
0
2
8
2
3
4

 

 

 

 

 

 

解析

一直二分开高度,通过高度与弦长推出半径,再算角度,最后及事实上的弧长进行比,并最后进行调整。

这种算法的便宜有以下几点;
1.采用相交弦定理,求来半径
2,只于求sita时采取了同等潮反三角函数,不像任何的算法,反复的求三角正弦,余弦啊各种·····尽量保留了精度。
3,突破往底老二分叉模式,并无求关于高度的calcu表达式,而是间接利用,以判断大小
4,最后,我看无比神奇的凡大神在错综复杂的题意下,找到了一个老大简单的单挑函数:依题长度增加做多不了一半,也就是是彼变异的扇形组最要命而是大凡半全面,那么在弦长一定之时光,给一个弧高就足以规定一个周,进而可确定这段弧长。

<Matchperson的辨析写的挺棒,这里粘一下>

平志独立的次分开问题,我们见面想到直接二瓜分答案dis,然后便可以计算产生这弧所在的无微不至之半径,紧接着就得请来弧长。用要来底弧长与真的的弧长做比来规定下一样浅第二私分的界定。

但是有只问题,怎么管算有之弧长满足单调性?可以yy一下拿走。
1.dis粗之时光:
图片 2
2.dis不胜的时:
图片 3

以木棍原长度不更换的景况下,dis越老,显然木棍越涨,所以弧长也尽管越发充分,满足单调性。

满足了单调性之后,我们就好安慰二分割了,这里还详尽说明一下哪告弧长:
图片 4
基于勾股定理,我们解(R-dis)^2+(len/2)^2=R^2,所以:
R^2-2*R*dis+dis^2+len^2/4=R^2
2*R*dis=dis^2+len^2/4
R=(dis+len^2/4/dis)/2
根据len’=2*θ*R=2*acos((R-dis)/R)*R(acos代表反三角函数,即知cos值求角度(弧度制)),就足以获取弧长。
仲瓜分的限制:弧顶多是半圆,所以dis最多是len/2。

出奇:当len=0或n=0或C=0时,答案就是0,最好特判掉。否则可能会见促成被0除错误。

解析

样例的前头四组数据,都生简短,直接搜索最老,然后模拟就可以,没什么好说的。但对于第五组数,就起接触坑了。我们见面发觉:如果按照正常解法一破50ml地配灰色颜料,答案明了不是4.所以,在此间我们设1ml、1ml地流,直到配满灰色的了。

Code

#include<cstdio>
#include<cmath>
#include<cstring>

using namespace std;

#define eps 1e-4

double l,c,ls,n,r,sita;

double solve(double a,double b)
{
    double left,right,mid;
    left=a;
    right=b;
    while(left+eps<right)
    {

        mid=(left+right)/2;
        r=l*l/8/mid+mid/2;
        sita=2*asin(l/2/r);
        if(sita*r>=ls)
            right=mid;
        else
            left=mid;
    }
    return left;
}

int main()
{
    while(~scanf("%lf%lf%lf",&l,&n,&c))
    {
        if(l<0||n<0||c<0)break;
        ls=l*(1+n*c);
        printf("%.3f\n",solve(0,l/2));
    }
    return 0;
}

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=15;
int a[maxn],b[maxn];
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int n,m,k;
    while(scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        scanf("%d",&m);
        sort(a,a+n);
        if(a[n-1]%50==0) k=a[n-1]/50;
        else k=a[n-1]/50+1;
        int t=0;
        for(int i=0;i<n;i++)
            b[i]=k*50-a[i];
        while(t<m)
        {
            if(b[2]==0)
            {
                k+=1;
                for(int i=0;i<n;i++)
                    b[i]+=50;
            }
            else
            {
                t++;
                b[0]--,b[1]--,b[2]--;
                sort(b,b+n,cmp);
            }
        }
        cout<<k<<endl;
    }
    return 0;
}

[POJ 1836] 士兵站队 (Alignment)

[POJ 2393] 酸奶制造厂 (Yogurt Factory)

题材叙述

在军事遭受,一个团是由战士组成的。在晨底检阅中,士兵们在主任面前站成一行。但官员对精兵们的序列并无令人满意。士兵们实在按照他们的号由小到大站成一列,但并无是依照高度顺序来站的。于是,长官让部分老将出列,其他留在队里的士兵没有交换位置,变成了还缺乏的一列。这个队满足一下规则:队伍里之各一个战斗员还至少可瞥见任何队伍的卓绝前沿或最后方,(如果一个精兵一旦看到部队的无比前沿或极后方,那么在他的前方或后,都不曾比较他大的食指)。

今日本顺序为有一个序列里之每个士兵的身高,计算出若要形成满足上述条件的班,长官至少需让小兵出列。

题材叙述

职责规定,一个酸奶制造厂,在N (1
<= N <= 10,000) 个星期日内,分别要奔外提供Y[i] (0 <= Y_i <=
10,000)单位之酸奶。已掌握是制造厂第i圆制造每单位酸奶之用呢C[i] (1
<= C_i <= 5,000),储存室储存每1单位酸奶1礼拜的开销也S (1 <= S
<= 100) 。问要形成这任务之绝小费用是有点。

输入

输入数据的第一执,包含一个整数n,表示原本列里士兵的数额。第二推行,包含n个浮点数(最多出五位小数),第i单浮点数表示队列中编号为i的精兵的身高hi。

中:2 <= n
<= 1000 ,且身高hi的取值范围[0.5,2.5]。

输入

首先履行:两只整数N和S

第2~n+1行:第i+1行包含两单整数C[i]和Y[i]

输出

饱含一个整数,表示要出列的极致少士兵屡次。

输出

一个平头,表示满足安排的顶小花费。注意:这个累或者会见超过32员整型。

样例数据

样例输入 样例输出
8
1.86 1.86 1.30621 2 1.4 1 1.97 2.2
4

 

 

 

 

样例数据

样例输入 样例输出
4 5
88 200
89 400
97 300
91 500
126900

 

 

 

 

 

解析

眼看道题嘛,就是深受队列里最少的小将出列,使班化这样一个则,如图-1。由于要求最少出列人数,也不怕是保留最多人,于是当即道题就起矣央最好丰富达到升子序列的DP做法。对第i私房,计算1~i的最丰富上升序列(长度也l)与i+1~n的尽丰富下降序列(长度也d),对富有的i,取l+d的太酷值max。答案就为n-max。二分+枚举也不过求解。

图片 5

 

                                             图-1

解析

贪。对于各一样圆的订单,维护最小花费:min_cost=min(C[i],min_cost+S)。

Code

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>

using namespace std;

int n;

double num[1111];
double up[1111];
double down[1111];

const int inf=(1<<31)-1;

int b1(double ss,int Left,int Right)
{
    int L=Left;int R=Right;
    int mid;
    while(L<R)
    {
        mid=(L+R)>>1;
        if(up[mid]>ss)
        {
            R=mid;
            mid=(L+R)>>1;
        }
        else if(up[mid]==ss)
        {
            return mid;
        }
        else
        {
            L=mid+1;
            mid=(L+R)>>1;
        }
    }
    return R;
}

int b2(double ss,int Left,int Right)
{
    int L=Left;int R=Right;
    int mid;
    while(L<R)
    {
        mid=(L+R)>>1;
        if(down[mid]<ss)
        {
            R=mid;
            mid=(L+R)>>1;
        }
        else if(down[mid]==ss)
        {
            return mid;
        }
        else
        {
            L=mid+1;
            mid=(L+R)>>1;
        }
    }
    return R;
}

int main()
{
    int ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lf",&num[i]);
    for(int i=1;i<=n;i++)
    {
        memset(up,0,sizeof(up));
        memset(down,0,sizeof(down));
        int lisnum=1;
        up[0]=-1;
        for(int j=1;j<=i;j++)
        {
            int index=b1(num[j],0,lisnum);
            if(index==lisnum)
                lisnum++;
            up[index]=num[j];
        }

        int ldsnum=1;
        down[0]=inf;
        for(int j=i+1;j<=n;j++)
        {
            int index=b2(num[j],0,ldsnum);
            if(index==ldsnum)
                ldsnum++;
            down[index]=num[j];
        }
        lisnum--;ldsnum--;
        ans=max(ans,lisnum+ldsnum);
    }
    printf("%d\n",n-ans);
}

Code

#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<iostream>

#define LL long long
#define MAXN 10010
#define INF 0x3f3f3f3f

using namespace std;

LL C[MAXN];
LL Y[MAXN];
LL cost;

int main()
{
    int MAX=INF;
    int N,S;
    scanf("%d%d",&N,&S);
    for(int i=1;i<=N;i++)
    {
        cin>>C[i]>>Y[i];
        if(C[i]>MAX+S)
            C[i]=MAX+S;
        MAX=C[i];
        cost+=C[i]*Y[i];
    }
    cout<<cost;
    return 0;
}

[POJ 3714] 突袭 (Raid)

[POJ 1877] 淹没 (Flooded!)

问题叙述

叫出A、B两个点集,每个集合包含N个点。现要求分别从少只点集中取出一个碰,使这片个点之偏离最小。

题材叙述

用一个区域分成r*c个方块,每个方块有来一个高程(可刚而依)。求当给区域注入指定容量的趟时,水面的海拔是稍微,以及被水淹没的正方占总方块数的比例。每个方块的面积也100m^2,水之容量单位也立方米。 

输入

输入的率先实践包含一个平头T,表示样例个数。
连下有T个样例,每个样例的率先行一个平头N
(1 ≤ N ≤ 100,000),表示每个组的触及的个数
紧接着有N行,每行有些许只整数X
(0 ≤ X ≤ 1,000,000,000) and Y (0 ≤ Y ≤
1,000,000,000),代表A组的各点的坐标。
又接着N行,每行有少独整数X
(0 ≤ X ≤ 1,000,000,000) and Y (0 ≤ Y ≤
1,000,000,000),代表B组的各点的坐标。

输入

多组用例,每组用例第一行事两个整数r和c表示区域行列数,然后是一个r*c的矩阵,矩阵元素呢对诺区域方块的海拔,最后是流入和的体积,以r=c=0结束输入 

输出

对此每个样例,输出两沾里最小的去,保留3员小数。注意少独点得来星星独不等之组。

输出

对于每组用例,输出注入和后水面的海拔以及为和淹没方块占总方块数的百分比 

样例数据

样例输入 样例输出
2
4
0 5
0 0
1 0
1 1
2 2
2 3
3 2
4 4
4
0 0
1 0
0 1
0 0
0 0
1 0
0 1
0 0
1.414
0.000

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

样例数据

样例输入 样例输出
3 3
25 37 45
51 12 34
94 83 27
10000
0 0
Region 1
Water level is 46.67 meters.
66.67 percent of the region is under water.

 

 

 

 

 

 

解析

任由集合限制的恳求最近触及对:
针对所有点先以x坐标不弱化排序,对x进行第二区划,得到点集S1,点集S2,通过递归求得S1,S2的卓绝小点对距d1,d2;D=min{d1,d2};合并S1,S2:找到在S1,S2划分线左右距为D的所有点,按y不减(不长为足以)排序;循环每个点找它后6单点的最小去;最后便求得最小点对离。
立刻道题出集聚限制嘛,把同集合之间点的去定为无根本大就行了。

解析

(Tips:
如果当POJ上一直莫名TLE,WA,RE,建议把默认语言的G++换成C++,玄学……)

总的来看就道题,首先使清楚是r*c的区域与矩阵一点事关都未曾,于是毫不犹豫改成为一排列的平维数组。此时又发现体积并无好算,于是来一个sort,此时的区域虽改为了如图-1所显示之榜样。现在,问题就是比较简单了:对于各级一样组数,我们唯有需要判定水面从左到右延伸至了哇一个职务就是能够判断覆盖方块数了(在每一个职位还产生一个体积范围)。而对此体积,运用小学的体积公式为就是整出来了。(注意浮点数精度误差)

图片 6

               
                      图-1

Code

#include<cstdio>
#include<algorithm>
#include<cmath>

#define INF 1<<30

using namespace std;

long long x[200010],y[200010];
int orderx[200010],ordery[200010],n;
double solve(int start,int end);

bool cmpx(int i,int j)
{
    if(x[i]<x[j])
        return 1;
    else 
        return 0;
}

bool cmpy(int i,int j)
{
    if(y[i]<y[j])
        return 1;
    else 
        return 0;
}

double disx(int i,int j)
{
    if(orderx[i]<n&&orderx[i]<n)
          return INF;
    else if(orderx[i]>=n&&orderx[i]>=n)
          return INF;
    else
      return sqrt((double)((x[orderx[i]]-x[orderx[j]])*(x[orderx[i]]-x[orderx[j]])+(y[orderx[i]]-y[orderx[j]])*(y[orderx[i]]-y[orderx[j]])));
}

double disy(int i,int j)
{
    if(ordery[i]<n&&ordery[j]<n)
              return INF;
    else if(ordery[i]>=n&&ordery[j]>=n)
              return INF;
    else
          return sqrt((double)((x[ordery[i]]-x[ordery[j]])*(x[ordery[i]]-x[ordery[j]])+(y[ordery[i]]-y[ordery[j]])*(y[ordery[i]]-y[ordery[j]])));
}

double min(double a,double b){return a>b?b:a;}

double min(double a,double b,double c)
{
    return min(a,min(b,c));
}

int main()
{
    int T,i,j;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=0;i<2*n;i++)
        {
            scanf("%d%d",x+i,y+i);
            orderx[i]=ordery[i]=i;
        }
        sort(orderx,orderx+2*n,cmpx);
        printf("%.3lf\n",solve(0,2*n-1));
    }
    return 0;
}


double solve(int start,int end)
{
    if(start+1==end)
       return disx(start,end);
    else if(start+2==end)
       return min(disx(start,start+1),disx(start,start+2),disx(start+1,start+2));
    else
    {
        int mid=start+(end-start)/2;
        double d=min(solve(start,mid),solve(mid+1,end));
        int t=0;
        for(int i=start;i<=end;i++)
           if(fabs((double)x[orderx[i]]-(double)x[orderx[mid]])<=d)
                    ordery[t++]=orderx[i];
        sort(ordery,ordery+t,cmpy);
        for(int i=0;i<t;i++)
           for(int j=i+1;j<min(end,i+6);j++)
                    d=min(d,disy(i,j));
        return d;
    }
}

Code

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

int n,m,T;
int i;
double v;
double land[1000];

int main()
{
    T=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(m==0&&n==0)
            return 0;
        for(i=0;i<n*m;i++)
            cin>>land[i];
        cin>>v;
        sort(land,land+n*m);
        for(i=0;i<n*m-1;i++)
        {
            if(v<(land[i+1]-land[i])*(i+1)*100)
                break;
            v-=(land[i+1]-land[i])*(i+1)*100;
        }
        double h=land[i]+v/(i+1)/100;
        if(v==0)
            h=1;
        printf("Region %d\n",T++);
        printf("Water level is %.2f meters.\n",h);
        printf("%.2f percent of the region is under water.\n",(i+1)/((double)(n*m))*100);
        printf("\n");
    }
    return 0;
}

[POJ 3122] 分馅饼 (Pie)

[POJ 1328] 雷达安装 (Radar Installation)

问题叙述

本人过生日要了F个对象来参加自己之生日party。总共发生N个馅饼,要将她平均分被每个人(包括我),并且每个人不得不于平块馅饼得到协调的那么同样客,并且分得的馅饼大小要一致,形状可以免平等,每块馅饼都是圆柱,高度一样。

题目叙述

我们假设海岸是无限延伸的直线,陆地在海岸的一边,大海在另一边。每个小岛是一个点位于大海那一片区域。详见图片;

每一个雷达的安装位置只能够在海岸线上,只能够覆盖半径为 d 的圆形区域。所以,如果小岛与雷达距离小于等于d才能够覆盖。

我们可以用笛卡尔积坐标系,定义海岸线是 x轴,大海在x 上方,陆地在x 轴下方,给你每个小岛在大海中的位置,并且给出雷达的覆盖范围 d ,你的任务是写一个程序,找到最少需要安装的雷达数量且能够覆盖所有的小岛。一个位置表示(x,y)坐标。

图片 7

     Figure A
Sample Input of Radar Installations

输入

第1实践:一个刚好整数,表示测试数据的组数。
以列一样组数据被:第1行包含两独整数,N和F
(1 ≤ N, F ≤ 10 000);第2推行包含N个整数,表示每一个馅饼的半径。

输入

输入是多组语句输入;

每行包含两个数 n 和 d:``n 代表小岛的数量,d 代表雷达的覆盖半径;

接下来n行是小岛的位置,用一个二维坐标来表示Xi,Yi;

当输入的 n 和 d 都为0,程序结束。

输出

于各级一样组数据,输出可能的无比特别体积。要求误差小于10^(-3),即至少保留四员小数。

输出

对于每组数据输出一个答案,每个答案占一行,输出最小需要的雷达数量,如果不能够满足要求,则输出 -1。

样例数据

样例输入 样例输出
3
3 3
4 3 3
1 24
5
10 5
1 4 2 3 4 5 6 5 4 2
25.1327
3.1416
50.2655

 

 

 

 

 

 

 

样例数据

样例输入 样例输出
3 2
1 2
-3 1
2 1
  
1 2
0 2
  
0 0 
Case 1: 2
Case 2: 1

 

 

 

 

 

 

 

 

解析

贪心的合计+二瓜分。复杂度为O(nlogM),M为初始时的high-low。初始状态,上界high为每个人分得奶酪的体积sum,下界low
= 0(或者是最好小片的奶酪)。然后二私分,每次的mid值为(low+high)/
2,然后因mid值(估计值)遍历n块奶酪,看看是mid值能分开被多少个人,如果份数大于等于f,表示mid偏小,low
= mid,反之high = mid。

小心:这里的圆周率pi应该尽量精确,否则易受噎精度。

解析

率先,我们用岛屿从左到右(x坐标从小到特别)进行排序。接下来,我们移动相同遍循环,计算起能挂第i只岛的雷达的坐标范围
[ll[1],rr[1]] (相当于是x轴上之线条)
,如图-2。接下来,我们从左到右再走相同赖巡回,这无异于赖,我们看这些同截段线段有小重合区域(这意味有几岛屿可一并用一个雷达),最后统计,求来答案。

图片 8

               
             图-2

Code

#include<cstdio>
#include<cmath>

double pi=acos(-1.0);
double sum,mid,le,ri,b[10000+11],max0;

int n,f,r;

double fl(double x)
{
    int su=0;
    for(int i=0;i<n;i++)
    {
        su+=(int)(b[i]/x);
    }
    return su;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        sum=0;
        scanf("%d %d",&n,&f);
        f++;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&r);
            b[i]=r*r*pi;
            sum+=b[i];
        }
        sum=sum/f;
        le=0.0;
        ri=sum;
        while(fabs(ri-le)>1e-6)
        {
            mid=(le+ri)/2;
            if(fl(mid)>=f)
            {
                le=mid;
            }
            else
            {
                ri=mid;
            }
        }
        printf("%.4f\n",le);
    }
}

Code

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
double x[10000],y[10000],ll[11000],rr[10000];
int main()
{
    int n,d;
    int cnt=1;
    while(cin>>n>>d)
    {
        if(n==0&&d==0)
            break;
        int flag=1,sum=1;
        for(int i=0;i<n;i++)
        {
            cin>>x[i]>>y[i];
            if(y[i]>d)
                flag=0;
        }
        cout<<"Case "<<cnt;
        cnt++;
        if(flag==0||d==0)
        {
            cout<<": -1"<<endl;
            continue;
        }
        int t;
        for(int i=0;i<n-1;i++)
        {
            for(int j=0;j<n-i-1;j++)
            {
                if(x[j]>x[j+1])
                {
                    t=x[j];
                    x[j]=x[j+1];
                    x[j+1]=t;
                    t=y[j];
                    y[j]=y[j+1];
                    y[j+1]=t;
                }
            }
        }
        for (int i=0;i<n;i++)
        {
            double s=sqrt(d*d-y[i]*y[i]);
            ll[i]=x[i]-s;
            rr[i]=x[i]+s;
        }
        double x=rr[0];
        for(int i=1;i<n;i++)
        {
            if(ll[i]>x)
            {
                x=rr[i];
                sum++;
            }
            if(rr[i]<x)
            {
                x=rr[i];
            }
        }
        cout<<": "<<sum<<endl;
    }
    return 0;
}

[POJ 2366] 总和的圣礼 (Sacrament of the sum)

[POJ 1018] 通讯系统 (Communication System)

题材叙述

既往,有一些感情破裂的哥们儿。为了抢救他们中的感情,兄弟两人每个人都备了一部分于他们来说可以救他们中情感的数字,这些数字可以救他们的情义也?(若于少数只列表中的个别是一个累,它们的同也10000,则我们看这些数字可以救他们中的情愫)。你的主次应该控制,是否出或于少个整数列表选择这样少单数字,来救援他们之真情实意。

问题叙述

Pizoor
Communications
Inc.要成立平等套通信系统,该通信系统要n种设备,而每种设备分别可起m1、m2、m3、…、mn个厂家提供生产,而每个厂家生产的同种设备还见面有个别独面的出入:带宽bandwidths
和 价格prices。

现行每种设备还各得1个,考虑到性价比问题,要求所挑选出来的n件设备,要教B/P最老。其中B为当下n件设备的带宽的极端小值,P为这n件设备的总价。

输入

每堆数(共2堆)的输入格式如下:每堆数之率先尽,包含一个整数N
( 1 <= N <= 50,000
),表示即列表中的数字的个数;接下N行,每一样履行包含一个整数A (
-32767<= A <=32767
)。输入数据保证:第一堆放数仍升序排列,第二堆积数以降序排列。

输入

第一履包含一个平头t (1
≤ t ≤ 10),表示有t组数据。

每组数据的率先履行包含一个整数n (1
≤ n ≤ 100),表示所急需的设施项目数。接下来闹n行,其中第i (1 ≤ i ≤
n)行的第一单整数mi (1 ≤ mi ≤
100)表示产第i种植装备的厂家数量,接下去当跟一行来零星少于变为对的整数,第一只代表带富,第二独象征标价。

输出

要是能够找到符合要求的简单单数,就输出”YES”,否则输出”NO”

输出

出口对于每一样组数而言的B/P的无限要命价值,保留三员小数。

样例数据

样例输入 样例输出
4
-175
19
19
10424
3
8951
-424
-788
YES

 

 

 

 

 

 

 

 

样例数据

样例输入 样例输出
1 3
3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110
0.649

 

 

 

 

 

解析

由个别单数列都稳步(连sort都不要),直接指向一个列表进行枚举,对其余一个列表进行次细分查找就尽了。

解析

自听说马上道题是一道DP题,但考虑到这是名缰利锁复习,还是用贪心+剪枝吧。

于不过小带富开始枚举,用贪心法选出带富逾等于最小带宽的低价格;然后再度于创新最酷的(B/P)的价,直到到最充分带富;如果打带富枚举上去,一定符合要求。

Code

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>

using namespace std;

int A[50000],B[50000];

int main()
{
    int n1,n2,mid,Max,Min;
    scanf("%d",&n1);
    for(int i=0;i<n1;++i)
        scanf("%d",&A[i]);
    scanf("%d",&n2);
    for(int i=0;i<n2;++i)
        scanf("%d",&B[i]);
    for(int i=0;i<n1;++i)
        for(Min=0,Max=n2-1,mid=(Max+Min)/2;Min<=Max;mid=(Max+Min)/2)
        {
            if(A[i]+B[mid]==10000)
            {
                printf("YES");
                return 0;
            }
            else if(A[i]+B[mid]>10000)
                Min=mid+1;
            else
                Max=mid-1;
        }
    printf("NO");
    return 0;
}

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;

const int Max=101;

struct node
{
    double b;
    double p;
};
node a[Max][Max];

double b[Max*Max];
int m[Max];
int bsize;

int cmp(const void *a,const void *b)
{
    return (*(double *)a)-(*(double *)b);
}

int main()
{
    int t,n;
    cin>>t;
    while (t--)
    {
        memset(a,0,sizeof(a));
        memset(m,0,sizeof(m));
        cin>>n;
        int i,j,k;
        int bsize=0;
        for (i=0;i<n;i++)
        {
            cin>>m[i];
            for (j=0;j<m[i];j++)
            {
                cin>>a[i][j].b>>a[i][j].p;
                b[bsize++]=a[i][j].b;
            }
        }
        qsort(b,bsize,sizeof(b[0]),cmp);
        double mmax=0;
        double mmin;
        double sump=0;
        double temp=0;
        for (i=0;i<=bsize-1;i++)
        {
            sump=0;
            int changFlag = 0;
            for (j=0;j<n;j++)
            {
                mmin=32767;
                for (k=0;k<m[j];k++)
                {
                    if (a[j][k].b>=b[i]&&a[j][k].p<mmin)
                    {
                        mmin=a[j][k].p;
                        changFlag = 1;
                    }
                }
                sump+=mmin;
            }
            if(!changFlag)
                break;
            temp=b[i]*1.0/sump;
            if(temp>mmax)
                mmax=temp;
        }
        printf("%.3lf\n",mmax);
    }
    return 0;
}

 

[POJ 3301] 德克萨斯的旅 (Texas Trip)

[POJ 1083] 移动桌子 (Moving Tables)

题材叙述

于和Dick同龙之远足后,Harry在温馨SUV的车门上发现了几个意想不到之小孔。而本地的维修店才出售正方形的玻璃微修补材料。现在,我们管车派及之小孔当做位于平面上整数坐标的点,问:
至少要同块多深面积的正方形修补材料才能挂已有所的小孔?

题材叙述

ACM公司租用的楼群如下图所示:

图片 9

眼看层楼的两头各发生200个屋子。现在局说了算以房内变换桌子。在动过程被,有且仅发生同一张桌子能够当过道内。因此,ACM公司欲同种植高效的配备来搬运桌子。已掌握,将同样摆桌子从一个室易到外一个间要不顶10分钟。由于拿几从房间i到房j移动的进程被,仅用下过道中之i~j的一部分。若两只台的活动非一起以同样段过道,就足以以拓展。例如下表所示:

图片 10

对各级一个房而言,仅来同样布置桌子可以于移进或移出。你的任务是描摹一个主次来援助计算所需要的至少时。

输入

首先实行包含一个整数T
(T ≤ 30),表示有T组测试数据。

对于各一样组数据,第一实践包含一个整数n
(n ≤
30),表示有n个小孔。接下来来N行,每行两单整数X和Y,分别表示一个小孔的横坐标和纵坐标。输入数据保证各一个小孔距离原点(0,0)不超过500个单位距离。

输入

输入包含T组数据。

对此各级一样组数据,第一履包含一个整数N
(1 <= N <=
200),表示需活动的桌子。接下来发生N行,每行两个整数s和t,表示桌子从s移动到t。

输出

对各级一样组数,输出一个零星各类小数,表示正方形材料的无限小面积。

输出

对各一样组数,输出完成移动所待的足足时。

样例数据

样例输入 样例输出
2
4
-1 -1
1 -1
1 1
-1 1
4
10 1
10 -1
-10 1
-10 -1
4.00
242.00

 

 

 

 

 

 

 

 

 

样例数据

样例输入 样例输出
3 
4 
10 20 
30 40 
50 60 
70 80 
2 
1 3 
2 200 
3 
10 100 
20 80 
30 50 
10
20
30

 

 

 

 

 

 

 

 

 

 

 

解析

碰巧开头看题,以为正方形不见面旋转,算算点的境界就行了,后来才发觉:
如果恰巧方形旋转起来,面积是出或回落的。下面是正解:
为了好计算,我们无叫刚刚方形旋转,而是让方形边始终跟坐标轴保持平行,让点转,三分点的旋转角度,范围[0,pi],每次转后统计横纵坐标最老差值
(计算边界) ,取单极度深价值就是为目前角度对应之正方形边长 。

图片 11

                             图-2

解析 

单纯需要将区间经过的地方计数,最后找到最好深计数就得了。答案的卓绝优性说明:题意可以据此区间图表示,即每一个间距为一个终极,如果少个区间范围相交,则在中间连上等同漫漫边。题目就是转发为求区间图的色数,由定理:区间图中色数=团数知道要最好特别团的顶点数即可。那么最充分团的顶峰数就是上述思路。[极致大团是呀?]

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>

using namespace std;

#define eps 1e-12
#define pi acos(-1.0)
#define maxn 33

struct node 
{
    double x,y;
    node spin(double a)
    {
        node ans;
        ans.x=x*sin(a)-y*cos(a);
        ans.y=x*cos(a)+y*sin(a);
        return ans;
    }
}a[maxn],b[maxn];

int T,n;

double cal(double x)
{
    for(int i=0;i<n;i++)b[i]=a[i].spin(x);
    double x1,x2,y1,y2;
    x1=x2=b[0].x,y1=y2=b[0].y;
    for(int i=1;i<n;i++)
        x1=min(x1,b[i].x),x2=max(x2,b[i].x),y1=min(y1,b[i].y),y2=max(y2,b[i].y);
    return max(x2-x1,y2-y1);
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        double l=0,r=pi,mid1,mid2,f1,f2;
        while(1)
        {
            mid1=(l+r)/2;
            mid2=(mid1+r)/2;
            f1=cal(mid1);
            f2=cal(mid2);
            if(abs(f1-f2)<eps)
                break;
            else if(f1<f2)
                r=mid2;
            else 
                l=mid1;
        }
        printf("%.2f\n",f1*f1);
    }
    return 0;
}

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

#define N 202

using namespace std;

int n,flag[N],T;

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        int a,b,res=0;
        scanf("%d",&n);
        memset(flag,0,sizeof(flag));
        for(int i=0;i<n;i++)
        {
            scanf("%d %d",&a,&b);
            if(a>b)
            {
                swap(a,b);
            }
            a=(a-1)>>1;
            b=(b-1)>>1;
            for(int j=a;j<=b;j++)
                flag[j]++;
        }
        for(int i=0;i<N;i++)
            res=max(res,flag[i]);
        printf("%d\n",res*10);
    }
    return 0;
}

[POJ 2503] 宝贝鱼翻译机 (Bablefish)

[HDU 1239] 再次呼叫地外文明(Calling Extraterrestrial Intelligence Again)

问题叙述

若碰巧自滑铁卢(Waterloo)搬至了一个新的不可开交城市。这里的人们都说着同样栽令人费解的外文方言。幸运的是,你产生相同依好帮您了解的词典。

问题叙述

吃有一个压倒4底整数m和一个真分数a/b,求最佳素数对p、q,使得a/b<=p/q<=1且pq<=m。最佳即为满足条件的频繁对准中pq最特别之等同对。

输入

输入包含最多100,000修词典条目,接下去有一个空行,其次是绝多100,000歌词之本来面目信息。
各一个词典条目包含用空格分开的星星个字符串S1和S2,其中S1凡译文,S2是原文。原始信息呢多执行,一行一个亟待翻译的单词。
输入数据保证各级一个单词的程长度不越10只字符。

输入

输入文件最多2000实行。每一样实行包含了三只整数:整数m,分子a,分母b。( 4
< m <= 100000 and 1 <= a <= b <= 1000 且满足 0 < a / b
< 1)

以三个0结尾。

输出

于各一个急需翻译的单词,输出翻译后的单词。若原始单词不设有在词典中,输出”eh”(不包含引号)。

输出

输出是一个由于正整数数对构成的阵。表示每一样组数遭到的p、q。

样例数据

样例输入 样例输出
dog ogday
cat atcay
pig igpay
froot ootfray
loops oopslay

atcay
ittenkay
oopslay
cat
eh
loops

 

 

 

 

 

 

 

 

样例数据

样例输入 样例输出
5 1 2
99999 999 999
1680 5 16
1970 1 1
2002 4 11
0 0 0
2 2
313 313
23 73
43 43
37 53

 

 

 

 

 

 

解析

自打小至异常排序,然后于每个询问,二分开查找。复杂度O(nlogn)。

解析

直接枚举查找:快速求出素数表后,运用二分查找检查时频繁是否也素数。(注意,由于是请求最好要命,所以由晚朝前面搜,直到j<z时退出)。

还要关注p的取值范围:[1,sqrt(n)] 

Code

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

struct node
{
    char s1[20],s2[20];
}a[100005];

int len;

int cmp(node a,node b)
{
    return strcmp(a.s2,b.s2)<0;
}

int main()
{
    len=0;
    char str[50];
    while(gets(str))
    {
        if(str[0]=='\0')
            break;
        sscanf(str,"%s%s",a[len].s1,a[len].s2);
        len++;
    }
    sort(a,a+len,cmp);
    while(gets(str))
    {
        int l=0,r=len-1,mid,flag=1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(strcmp(str,a[mid].s2)==0)
            {
                printf("%s\n",a[mid].s1);
                flag=0;
                break;
            }
            else if(strcmp(str,a[mid].s2)<0)
                r=mid-1;
            else
                l=mid+1;
        }
        if(flag)
            printf("eh\n");
    }
    return 0;
}

Code

#include<cstdio>
#include<cmath>
#include<cstring>

using namespace std;

int prim[100005],is[100005];
int num=0;

int Find(int v)
{
    int m;
    int l=1,h=num;
    while(l<h)
    {
        m=(l+h)/2;
        if(prim[m]==v)
            return 1;
        if(prim[m]<v)
            l=m+1;
        else
            h=m;
    }
    return 0;
}

int main()
{
    int m,a,b,Max,j,i,x,zx,zi,z;
    double t;
    int s,e=(int)(sqrt(0.0+100000)+1);
    memset(is,1,sizeof(is));
    prim[++num]=2;
    is[0]=is[1]=0;
    for(i=4;i<=100000;i+=2)
        is[i]=0;
    for(i=3;i<e;i+=2)
        if(is[i])
        {
            prim[++num]=i;
            for(s=i*2,j=i*i;j<=100000;j+=s)
                is[j]=0;
        }
    for(;i<100000;i+=2)
        if(is[i])
            prim[++num]=i;
    while(scanf("%d%d%d",&m,&a,&b)!=EOF)
    {
        z=0;
        if(m==0 && a==0 && b==0)
            break;
        t=a*1.0/b;
        for(int j=m;j>=1;j--)
        {
            if(j<z)
                break;
            Max=(int)sqrt(0.0+j);
            for(i=Max;i>=1;i--)
            {
                x=j/i;
                if(x*t<=i && x>=i)
                    if(Find(i)&&Find(x))
                        if(x*i>z)
                        {
                            zx=x;
                            zi=i;
                            z=x*i;
                        }
            }
        }
        printf("%d %d\n",zi,zx);
    }
    return 0;
}

[POJ 3737] UmBasketella (UmBasketella)

[UVA 1292] 战略游戏 (Strategic Game)

问题叙述

为定圆锥的表面积S,求者圆锥的极端大体积V,以及这它的高h与底面半径r。

题材叙述

鲍勃喜欢玩战略游戏。现在来同座都,其里面的征途构成了同样株树。鲍勃可以以某些城市使一个士兵守护,该士兵可以瞭望到具备与拖欠城持续的度。问鲍勃最少要派多少个战士,才会把富有的界限还瞭望到。

比如说,在底下就株树中,只待拿战士在节点1即使好瞭望到横之限了。

图片 12

 

输入

输入数据被有差不多个测试点,每个测试点只含一个实数
S, 代表圆锥的表面积。表面积 1≤S≤10000.

输入

输入文件包含多组数据。
每一样组数包含了针对性树之以下描述:
1>
节点数N;
2>
接下来N行,每一行对一个节点进行实际讲述,其格式如下:
节点编号:(与该总是的征程数m)
连接的节点1 一连的节点2 一连的节点3 ……连接的节点m

输出

于每个测试点,输出应该包含三执:
首先尽输出最大体积V;
亚行输出高h;
老三实行输出底面半径r;
不无实数应该四放弃五称到0.01。

输出

对每一样组数,输出需要的极少士兵屡次。

样例数据

样例输入 样例输出
30
10.93
4.37
1.55

 

 

 

 

 

样例数据

样例输入 样例输出

4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)

1
2

 

 

 

 

 

 

 

 

 

解析

枚举底面圆半径,算圆锥的体积。可以列出表达式,满足三分,因此可三私分枚举底面圆半径。

解析

无限少点覆盖问题
好为此树形DP解决,我们拿管根树抽象成一棵有根树,0为树根。对于自由一个节点i来说,设dp[i][0]意味着以该节点不放士兵,dp[i][1]代表于该节点放置士兵。
这就是说做他的子节点就可以赢得状态转移方程
dp[i][1]=sum(dp[k][0])+1
k为i的子节点,下同,因为以节点没放开,则子节点一定要是推广
dp[i][0]=sum(min(dp[k][0],dp[k][1]))
因为依照节点放了,所以取子节点放以及非放开之卓绝小值
末答案就是是min(dp[0][0],dp[0][1])

<三分开查找>

Code

#include<iostream>  
#include<vector>  
#include<cstring>  
#include<cstdio>  
#include<algorithm>  
#include<cmath>  
using namespace std;  

const int maxn = 1600;  
int dp[maxn][2];  
int n;  
vector<int> tree[maxn];  

int min(int a,int b)  
{  
    return a<b?a:b;  
}  

void dfs(int fa,int now)  
{  
    dp[now][0] = 0;  
    dp[now][1] = 1;  

    int len = tree[now].size();  
    int i;  

    for(i=0;i<len;i++)  
    {  
        int t=tree[now][i];  
        if(t!=fa)  
        {  
            dfs(now,t);  
            dp[now][0] += dp[t][1];  
            dp[now][1] += min(dp[t][0],dp[t][1]);  
        }  
    }  

}  


int main()  
{  
    while(~scanf("%d",&n))  
    {  
        int i;  
        for(i=0;i<n;i++)  
        {  
            tree[i].clear();  
        }  
        for(i=0;i<n;i++)  
        {  
            int b;  
            int a;  
            int j;  
            scanf("%d:(%d)",&a,&b);  
            for(j=0;j<b;j++)  
            {  
                int x;  
                scanf("%d",&x);  
                tree[a].push_back(x);  
                tree[x].push_back(a);  
            }  
        }  
        dfs(-1,0);  
        cout<<min(dp[0][0],dp[0][1])<<endl;  
    }  
    return 0;  
}
概念

于二分寻觅的根底及,在右侧区间(或错区间)再进行相同软第二分叉,这样的寻找算法称为三分寻觅,也便是三分法。三私分查找通常用来很快确定最值。

次瓜分查找所面向的物色行列的要求是:具有单调性(不自然严格单调);没有单调性的行不是使用二细分查找。

而与第二划分查找不同之是,三瓜分法所面向的寻找行列的渴求是:序列为一个凸性函数(例如二次函数)。通俗来讲,就是欠队必须发一个绝可怜价值(或最小值),在尽老价值(最小值)的左手序列,必须满足不严厉单调递增(递减),右侧序列必须满足不严格单调递减(递增)。如图-2,表示一个闹极度可怜价值的凸性函数:

图片 13

                                          图-3

①暨二分法类似,先取整个区间的中间值mid=(left+right)/2。

mid=(left+right)/2; 

②双重沾右侧的中等值Mid-mid=(mid+right)/2。

Mid_mid=(mid+right)/2;

③要觉察mid比Mid-mid更贴近最值,我们就算舍弃右区间,否则我们舍弃左区间。

比较mid与Mid-mid谁最接近最值,只待确定mid所当的函数值与Mid-mid所于的函数值的分寸。当最值为最可怜价值经常,mid与midmid中于生之良本更加贴近最值。最值为无限小值时倒。 

if(cal(mid)>cal(Mid_mid))  
    right=Mid_mid;  
else  
    left=mid;  

④重复①②③步骤,直到找到最好值。

[POJ 3617] 最佳奶牛序列 (Best Cow Line)

<另一样种植思路>
double three_devide(double low,double up)  
{  
    double m1,m2;  
    while(up-low>=eps)  
    {  
        m1=low+(up-low)/3;  
        m2=up-(up-low)/3;  
        if(f(m1)<=f(m2))  
            low=m1;  
        else  
            up=m2;  
    }  
    return (m1+m2)/2;  
}  

 

[guognib的老三划分模板]

问题叙述

老乡约翰带在他的奶牛们去到一个竞赛。奶牛们排成一列,依次取出每头奶牛名字的首字母组成队名。为了获得一个字典序最小的队名。约翰要重新排列奶牛队伍,排列规则是这么的:他只能拿奶牛队列的队头或队尾依次加入新队列的队尾,直到所有奶牛全部入到新队列为止。问他能够收获的字典序最小的队名?

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

#define eps 10e-6

using namespace std;

const double pi=acos(double(-1));

double S;

double cal(double r)
{
    double R=S/pi/r-r;
    double h=sqrt(R*R-r*r);
    return h*pi*r*r/3;
}

int main()
{
    while(~scanf("%lf",&S))
    {
        double l=0,r=sqrt(S/pi);
        double m1,m2,v1,v2;
        while(l+eps<r)
        {
            m1=l+(r-l)/3;
            m2=r-(r-l)/3;
            v1=cal(m1);
            v2=cal(m2);
            if(v1<v2)l=m1;
            else r=m2;
        }
        double R=S/pi/r-r;
        double h=sqrt(R*R-r*r);
        double V=h*pi*r*r/3;
        printf("%.2f\n%.2f\n%.2f\n",V,h,r);
    }
    return 0;
}

输入

第1执包含一个平头N,表示奶牛的到底数量。

第2及N+1行描述每一样匹奶牛。第i+1行表示于原来序列中编号为i的奶牛的首字母。

[POJ 1987] 距离统计 (Distance Statistics)

输出

字典序最小之字符串。

问题叙述

Farmer
John现在受有一个平头K (1 <= K <=
1,000,000,000),要求你算产生相隔路程不超过K的农场的对数。
(Tips:1>被算的农场必须是见仁见智的点滴独农场;2>农场内的路途由道路的长度控制)

样例数据

样例输入 样例输出
6
A
C
D
B
C
B
ABCBCD

 

 

 

 

 

 

 

输入

第1行:包含两个整数N
(2 <= N <= 40,000)和M (1 <= M <
40,000)。N表示农场数,M表示道路反复。
第2~M+1行:每一样履让闹一致长条道的信息F1、F2(连接的鲜单农场)、L(道路长度,1
<= L <=
1000)、D(从F1届F2的趋向,用N、S、W、E表示,在主题中无图)
第M+2行:一个整数K。

解析

贪婪就尽。每次打达到以及从下选择最为小的,若当则向中搜索。

输出

符合要求的农场对数。

Code

#include<cstdio>
#include<cstring>
#include<iostream>

#define MAXN 2010

using namespace std;

int n,str[MAXN];

int main()
{
    scanf("%d",&n);
    char ch;
    for(int i=0;i<n;i++)
    {
        getchar();
        ch=getchar();
        str[i]=ch-'A';
    }
    int pre=0,last=n-1,Count=0;
    for(int i=0;i<n;i++)
    {
        if(str[pre]==str[last])
        {
            int pr=pre,la=last,flag=0;
            while(pr<=la)
            {
                if(str[pr]<str[la])
                {
                    printf("%c",str[pre]+'A');
                    Count++;
                    flag=1;
                    pre++;
                    break;
                }
                else if(str[pr]>str[la])
                {
                    printf("%c",str[last]+'A');
                    Count++;
                    flag=1;
                    last--;
                    break;
                }
                pr++,la--;
            }
            if(!flag)
            {
                printf("%c",str[pre]+'A');
                Count++;
                pre++;
            }
        }
        else if(str[pre]<str[last])
        {
            printf("%c",str[pre]+'A');
            Count++;
            pre++;
        }
        else
        {
            printf("%c",str[last]+'A');
            Count++;
            last--;
        }
        if(Count==80)
        {
            Count=0;
            printf("\n");
        }
    }
    if(Count)
        printf("\n");
    return 0;
}

样例数据

样例输入 样例输出
7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
10
5

 

 

 

 

 

 

 

 

<样例解释>

有5对准路途不超过10的农场: 1-4
(3), 4-7 (2), 1-7 (5), 3-5 (7) 和 3-6 (9)。

[POJ 3069] 萨鲁曼的师 (Saruman’s Army)

解析

塑造的触及分治”裸题”。

1、把当时棵无根本树为1乎根本节点,使其成一株有根树。
2、对于每棵现在如拍卖的塑造,进行如下处理:
(1)遍历这株树,找到有一个端点为彻底,路径长度不超过k的路总数
(2)通过(1)求出底结果求和,枚举+二细分计算产生有长度不超过k的之路子总数
(3)去重新:也不怕是抹(2)中计算起重叠的路径有
(4)找到这株子树的主导,递归处理这棵子树,也就是是重复步骤2
3、统计答案并出口

[尚未看明白树分治?]
 你还得阅读漆子超的国家集训队论文《分治算法在培养的门径问题中之应用》

题材叙述

萨鲁曼要对准自己之一律列军队展开监视,因此他如果给这等同排列军队受到的片段士兵监视的权。但各国一个蹲点的老总只是能够遮盖距离自己R个单位中的兵(包括第R独)。现在,若一旦盖整支军队,至少要多少只监视的小将?

Code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>

#define MAX 40005

using namespace std;

int tot=0,ans=0;
int n,m,k,to[2*MAX],next[2*MAX],head[MAX],value[2*MAX];
int u[MAX],t,size[MAX],f[MAX],done[MAX];

struct wbysr
{
    int belong,dis;
}a[MAX];

bool cmp(wbysr a1,wbysr a2)
{
    return a1.dis<a2.dis;
}

void add(int from,int To,int weight)
{
    to[++tot]=To;
    next[tot]=head[from];
    value[tot]=weight;
    head[from]=tot;
}

void dfs(int x,int fa)
{
    u[++t]=x;
    size[x]=1;
    f[x]=0;
    for(int i=head[x];i;i=next[i])
        if(!done[to[i]]&&to[i]!=fa)
            dfs(to[i],x),size[x]+=size[to[i]],f[x]=max(f[x],size[to[i]]);
    return;
}

int find_root(int x)
{
    t=0;
    dfs(x,0);
    int Min=0x7fffffff,p;
    for(int i=1;i<=t;i++)
        if(max(size[x]-size[u[i]],f[u[i]])<=Min)
            Min=max(size[x]-size[u[i]],f[u[i]]),p=u[i];
    return p;
}

void dfs2(int x,int fa,int Belong,int dist)
{
    a[++t].belong=Belong;
    a[t].dis=dist;
    for(int i=head[x];i;i=next[i])
        if(!done[to[i]]&&to[i]!=fa)
            dfs2(to[i],x,Belong,dist+value[i]);
    return;
}

inline void calc(int x)
{
    t=0;
    a[++t].belong=x;
    a[t].dis=0;
    for(int i=head[x];i;i=next[i])
        if(!done[to[i]])
            dfs2(to[i],x,to[i],value[i]);
    sort(a+1,a+1+t,cmp);
    int r=t,same[MAX]={0};
    for(int i=1;i<=t;i++)
        same[a[i].belong]++;
    for(int l=1;l<=t;l++)
    {
        while(a[l].dis+a[r].dis>k&&r>l)
            same[a[r].belong]--,r--;
        same[a[l].belong]--;
        if(r>l)
            ans+=r-l-same[a[l].belong];
    }
}

inline void work(int x)
{
    int root=find_root(x);
    done[root]=1;
    calc(root);
    for(int i=head[root];i;i=next[i])
        if(!done[to[i]])
            work(to[i]);
    return;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int a1,a2,a3;
        char ch;
        scanf("%d%d%d %c",&a1,&a2,&a3,&ch);
        add(a1,a2,a3);
        add(a2,a1,a3);
    }
    scanf("%d",&k);
    ans=0;
    work(1);
    printf("%d\n",ans);
    return 0;
}

 

Time:
2017-07-15

输入

输入包含多组数。每一样组数据因个别独整数R和N开始,R (0
≤ R ≤ 1000)表示士兵会监视的限制,N( 1 ≤ N ≤
1000)表示马上同样排军队的新兵屡次。接下来一尽包含N个整数,表示每一个老将所处的职位X (
1 ≤ X ≤ 1000)。当R=N=-1时,输入数据了。

输出

于各一样组数据,输出最少要之老总屡次。

样例数据

样例输入 样例输出
0 3
10 20 20
10 7
70 30 1 7 15 20 50
-1 -1
2
4

 

 

 

 

 

 

解析

从今一个请勿覆盖的岗位上遍历,找到满足距离小于
R
的卓绝右面边的触及,这个点必当一个装置的放位置,然后打之职位找到下手的最好小之未可知遮住到的职务,这个岗位作下一样浅的起点…循环下去,直到有的接触都被遮盖到。

Code

#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iostream>

#define MAXN 1010

using namespace std;

int army[MAXN];

int R,N;

int main()
{
    while(scanf("%d%d",&R,&N)!=EOF)
    {
        if(R==-1&&N==-1)
            return 0;
        for(int i=1;i<=N;i++)
        {
            scanf("%d",&army[i]);
        }
        sort(army+1,army+N+1);
        int i=1,cnt=0;
        while(i<=N)
        {
            int bg=army[i++];
            while(i<=N&&army[i]<=bg+R)
            {
                i++;
            }
            int st=army[i-1];
            while(i<=N&&army[i]<=st+R)
            {
                i++;
            }
            cnt+=1;
        }
        printf("%d\n",cnt);
        memset(army,0,sizeof(army));
    }
}

[POJ 3253] 修理篱笆 (Fence Repair)

问题叙述

Farmer
John要失去举行篱笆,他一共需要N块木板,也量出每块木板需要多长。他打了如此一整块木板,这个木板的长短是所有需要的木板长度的与。但是他从没锯子。于是他找朋友去借锯子。可是朋友要是收费。收费是这样的,锯开平块长也L的木板收费L元。请问Farmer
John使用外对象之锯子,最少要花费多少钱。

输入

第1执:
包含一个整数N (1 ≤ N ≤ 20,000) ,表示所要木板的数量。
第2顶N+1行:每行一个平头,表示一致片木板的长短L
(1 ≤ L ≤ 50,000)。

输出

一个整数,表示Farmer
John最少花费的金额。

样例数据

样例输入 样例输出
3
8
5
8
34

 

 

 

 

 

 

解析

是因为要要费最小,因此非常轻掌握,我们各个一样软用切掉顶丰富之那一个片,来预防那有每当背后的精打细算着受数折叠加进花费中。当然,如果我们一直用sort排序的言语,肯定会晚点,所以我们设就此事先队列。做就道题时究竟起种植“合并果子”的觉得。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>

using namespace std;

priority_queue<int,vector<int>,greater<int> > pq;

int main()
{
    int n(0);
    cin>>n;
    while(cin>>n)
    {
        pq.push(n);
    }
    long long sum(0);
    int l1(0),l2(0);
    while(pq.size()>1)
    {
        l1=pq.top();
        pq.pop();
        l2=pq.top();
        pq.pop();
        sum = sum+l1+l2;
        pq.push(l1+l2);
    }
    cout<<sum;
    return 0;
}

[POJ 2376] 打扫谷仓 (Cleaning Shifts)

题目叙述

农民约翰让他的N头奶牛们打扫谷仓。他把同龙分成T个时刻段,第一只日子段也1,最后一个时光段为T。第i条奶牛愿意从第Si单日子段工作到第Ti只时间段。问尽少用有些奶牛,才能够管各级一个时空段都发生奶牛在工作。如果非克确保,则输出-1.

输入

第1执行:两个整数N
(1<= N <=25,000)和T (1<= T <=1,000,000)。
第2至N+1行:每一样尽包含一组开时以及终止时,表示同样头奶牛工作的岁月段。

输出

出口一个平头,表示最少需要有些头奶牛。

样例数据

样例输入 样例输出
3 10
1 7
3 6
6 10
2

 

 

 

 

 

解析

立刻书乍一押,不就是是距离覆盖问题啊?
[CQBZOJ上的距离覆盖问题] 

先期对各个一个岁月段(其实就算是线条)按左端点由小到大进行排序,从岁月段1开头同段子同样段子地属上来,连接时,在上下两长长的线段有交点的前提下如新的右端点最远,这样就是可知保证使用最少的线,即奶牛数最好小。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

typedef long long ll;

const int maxn = 25000 + 5;
const int maxd = 1000000 + 5;

struct Edge
{
    int x;
    int y;
}cow[maxn];

int N,T;
int X,Y;

bool cmp(Edge a,Edge b)
{
    if(a.x==b.x) return a.y>b.y;
    return a.x<b.x;
}

int main()
{
    X=0;
    Y=0;
    scanf("%d%d",&N,&T);
    for(int i=0;i<N;i++)
    {
        scanf("%d%d",&cow[i].x,&cow[i].y);
        if(cow[i].x==1)
            X=1;
        if(cow[i].y==T)
            Y=1;
    }
    sort(cow,cow+N,cmp);
    if(X==0||Y==0)
    {
        printf("-1\n");
        return 0;
    }
    int ans=1,End=0;
    int Start=cow[0].y;
    int maxy=cow[0].y;
    while(true)
    {
        while(End+1<N&&cow[End+1].x<=Start+1)
        {
            End++;
            if(cow[End].y>maxy)
            {
                maxy=cow[End].y;
            }
        }
        if(maxy!=Start)
        {
            ans++;
            Start=maxy;
        }
        else
        {
            if(End==N-1)
            {
                break;
            }
            else
            {
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

[POJ 3190] 挤奶预订 (Stall Reservation)

题目叙述

有N头奶牛,(1<=N<=50,000),每头奶牛只当特定的光阴段内[A,B]外才甘心挤奶(1<=A,B<=1,000,000)。一个挤奶机只能以挤一匹奶牛。农夫约翰最少需要预备稍个挤奶机,才会满足所有奶牛的挤奶需求。

输入

第1执行:一个整数N,表示奶牛数。
第2届N+1行:每一样执包含两个整数,分别表示同样匹奶牛愿意挤奶的开端日以及了结时间。

输出

第1推行:输出所需要之挤奶机的起码数量。
第2届N+1行:第i+1行的平头表示第i条奶牛所采用的挤奶机的号。

样例数据

样例输入 样例输出
5
1 10
2 4
3 6
5 8
4 7
4
1
2
3
2
4

 

 

 

 

 

 

<样例解释>

下是挤奶机的时刻安排表:(其它合理答案都只是)

图片 14

解析

先期随奶牛要求的年月起始点进行自小至好排序,然后保安一个预队列,里面盖曾上马挤奶的奶牛的结时早呢先行。然后每次仅需要检讨时是不是有奶牛的挤奶工作已就的机即可,若发生,则转移那台机械进行工作。若没,则加以相同令新的机。

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;

const int maxn=50000+10;

int order[maxn];

struct Node
{
    int st,en,pos;
    friend bool operator<(Node a,Node b)
    {
       if(a.en==b.en)
        return a.st<b.st;
       return a.en>b.en;
    }
}node[maxn];

bool cmp(Node a,Node b)
{
    if(a.st==b.st)
        return a.en<b.en;
    else
        return a.st<b.st;
}

priority_queue<Node>Q;

int main()
{
    int n,ans;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&node[i].st,&node[i].en);
            node[i].pos=i;
        }
        sort(node+1,node+1+n,cmp);
        ans=1;
        Q.push(node[1]);
        order[node[1].pos]=1;
        for(int i=2;i<=n;i++)
        {
            if(!Q.empty()&&Q.top().en<node[i].st)
            {
               order[node[i].pos]=order[Q.top().pos];
               Q.pop();
            }
            else
            {
                ans++;
                order[node[i].pos]=ans;
            }
            Q.push(node[i]);
        }
        printf("%d\n",ans);
        for(int i=1;i<=n;i++)
            printf("%d\n",order[i]);
        while(!Q.empty())  Q.pop();
    }
    return 0;
}

[POJ 3040] 津贴 (Allowance)

题目叙述

用作针对勤勤恳恳工作的贝茜的嘉奖,约翰曾控制开始开发贝茜一个每周津贴。
约翰有N
(1≤N≤20)种币值的硬币,面值小的硬币总能够整除面值较生之硬币。(比如说,币值有如下几种植:1美分,5美分,10美分,50美分…)利用给定的这些硬币,他就要每周付给贝茜一定金额之补贴C
(1 <= C <= 100,000,000)。

要帮助他计算起他极其多会被贝茜发几周的贴。

输入

第1行:2个用空格隔开的整数N和C。

第2届N+1行:每行两独整数表示一致种币值的硬币.第一单整数V
(1 <= V <= 100,000,000),表示币值。

老二个整数B (1
<= B <= 1,000,000),表示约翰拥有的这种硬币的个数。

输出

一个平头,表示约翰付给贝茜津贴得太多的周数。

样例数据

样例输入 样例输出
3 6
10 1
1 100
5 120
111

 

 

 

 

 

解析

开班看题目里之整除关系时,整个人口是了懵逼的:这是什么呀?后来思维呢就算想接了,这个法实在即便是解题的重要。

于面值超过C的硬币自然不用说。一枚用平等圆。
对面值小于C的硬币。我们先行考虑一个C的方案。要使用的周数最多我们当将使钱之利用率最要命。也就是说损失的钱太少,尽量不要跨越C太多。在非超过C的状下于大面值和小面值的优先使用大面值的。因为有些面值的结缘而收获大面值(整除关系)。留下多少面值为后面的整合最出色的可能性越来越老。如这种方针下并未凑够C的语就是寻找一个无比小之面额。使得组合值大于C。(使损失价值最小)

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>

const int INF=0x3f3f3f3f;

using namespace std;

struct node
{
    int val,mou;
}mon[25];

int n,c;
int need[25];

bool cmp(node a,node b)
{
    return a.val<b.val;
}

int main()
{
    int i,ans,ti,rest,lim,mday;
    while(~scanf("%d%d",&n,&c))
    {
        ans=0;
        lim=-1;
        for(i=0;i<n;i++)
            scanf("%d%d",&mon[i].val,&mon[i].mou);
        sort(mon,mon+n,cmp);
        for(i=n-1;i>=0;i--)
            if(mon[i].val>=c)
               ans+=mon[i].mou;
            else
            {
                lim=i;
                break;
            }
        while(1)
        {
            memset(need,0,sizeof need);
            rest=c;
            for(i=lim;i>=0;i--)
            {
                if(!mon[i].mou||!rest)
                    continue;
                ti=rest/mon[i].val;
                ti=min(ti,mon[i].mou);
                need[i]=ti;
                rest-=ti*mon[i].val;
            }
            if(rest)
            {
                for(i=0;i<=lim;i++)
                {
                    if(mon[i].val>=rest&&(mon[i].mou-need[i]))
                    {
                        need[i]++;
                        rest=0;
                        break;
                    }
                }
                if(rest)
                    break;
            }
            mday=INF;
            for(i=0;i<=lim;i++)
                if(need[i])
                mday=min(mday,mon[i].mou/need[i]);
            ans+=mday;
            for(i=0;i<=lim;i++)
                mon[i].mou-=mday*need[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}

[POJ 1862] Stripies (Stripies)

题目叙述

给出N个物体,分别叫闹每个的成色,并且两只物体(假设质量分别吗m1,m2)相撞的时光成为一个体,质量为2*sqrt(m1*m2),并且独自见面面世些微独简单个物品磕碰的景况。问最终会得到的物体的极小质量是多少。

输入

第1执包含一个整数N (1
<= N <= 100) 。接下来的N行,每行一个平头,表示一个物体的成色m (
1<= m <= 10,000 )。

输出

一个整数,表示极度小质量。

样例数据

样例输入 样例输出
3
72
30
50
120.000

 

 

 

 

 

解析

率先让闹贪心策略:每次选个别个当前极其可怜的数值进行演算,直到剩余一个物品。使用优先队列处理比较方便。

咱得以如此说明:假设三单物体,质量分别吗
a,b,c,(a>=b>=c)。可以证明:2*sqrt(2*c*sqrt(a*b)) <=
2*sqrt(2*a*sqrt(b*c)) 。

Code

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        priority_queue<double> q;
        for(int i=0;i<n;++i)
        {
            double tp;
            cin>>tp;
            q.push(tp);
        }
        while(q.size()>1)
        {
            double a=q.top();q.pop();
            double b=q.top();q.pop();
            double tp=2*sqrt(a*b);
            q.push(tp);
        }
        printf("%.3f\n",q.top());
    }
    return 0;
}

[POJ 3262] 保护花朵 (Protecting the Flowers)

题目叙述

N (2 ≤ N ≤
100,000)头奶牛在Farmer John的园林里吃花费,现在以掩护花朵,Farmer
John要用这些奶牛都带来回牛棚里去。第i头牛离牛圈有Ti (1 ≤ Ti ≤
2,000,000)分钟的里程, 在待被送转牛棚的又,这头牛还要每分钟吃少Di (1
≤ Di ≤ 100)朵花。而Farmer
John每次只能带来一条奶牛回到牛棚。

而今,要求请出奶牛们在剩余的日子里最好少会吃少多少朵花?

输入

第1履:包含一个整数N。
第2及N+1行:每一样行包含两个整数Ti和Di,分别表示奶牛回到牛棚需要之日与各分钟吃少的花朵。

输出

含有一个平头,表示奶牛们最为少吃的花朵数。

样例数据

样例输入 样例输出
6
3 1
2 5
2 3
3 2
4 1
1 6
86

 

 

 

 

 

 

 

解析

对牛进行排序,排序的规范是,假而牛A同牛B要挑同匹赶走,我们率先使摘破坏最可怜的一样峰牛赶走,留破坏小之牛。他们的毁坏在呢麽计算也?假设先赶走牛A,那么牛B造成的损失是2×TA×DB,先赶走牛B,那么牛A造成的损失是2×TA×DB,所以,只要判断TA×DB与TA×DB谁死,就懂得该先赶走谁了,所以数组排序的专业虽是Ti×Dj>Tj×Di

Code

#include<cstdio>
#include<cstring>
#include<algorithm>

#define LL long long 
#define INF 0x3f3f3f3f

using namespace std;

struct node
{
   LL x;
   LL y;      
}a[100010];

int cmp(node n,node m)
{
   return n.y*m.x>m.y*n.x;
}

int main()
{
    int n;
    LL sum,num;
    while(scanf("%d",&n)!=EOF)
    {
        sum=0;
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
        {
            scanf("%I64d %I64d",&a[i].x,&a[i].y);
            sum+=a[i].y;
        }
        sort(a,a+n,cmp);
        num=0;
        for(int i=0;i<n;i++)
        {
           sum-=a[i].y;
           num+=sum*(a[i].x*2);
        }
        printf("%I64d\n",num);
    }
    return 0;
}

 

Time:
2017-07-14

 

相关文章