[2014 北京网络赛]

来源:互联网 发布:原生js ajax 跨域 编辑:程序博客网 时间:2024/04/27 13:33

02 hdu 5033 Building

题目意思:

数轴上有n根柱子,每根柱子有个位置坐标和高度,有q个询问,询问从位置qi能看到的角度(保证左右至少有一个柱子)

解题思路:

单调栈维护一个凸性柱子序列。

离线处理所有的查询,排序,然后扫一遍qi,把柱子插进去,更新单调栈。注意查询位置也要更新栈。

代码:

//#include<CSpreadSheet.h>#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#include<cmath>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 110000struct Inf{    double xi,hi;}inf[Maxn];int n,q,L[Maxn],R[Maxn],sta[Maxn];struct Sa{    double xi;    int pos;}sa[Maxn];double be[Maxn];bool cmp1(struct Inf a,struct Inf b){    return a.xi<b.xi;    //return a.hi<b.hi;}bool cmp2(struct Sa a,struct Sa b){    return a.xi<b.xi;}bool iscan(int top,int topp,int la){    if(((inf[top].hi-inf[la].hi)/(inf[la].xi-inf[top].xi))<=((inf[topp].hi-inf[top].hi)/(inf[top].xi-inf[topp].xi)))        return true;    return false;}bool iscan1(int top,int topp,int la){    if(((inf[top].hi-inf[la].hi)/(inf[top].xi-inf[la].xi))<=((inf[topp].hi-inf[top].hi)/(inf[topp].xi-inf[top].xi)))        return true;    return false;}int main(){    //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);   int t;   scanf("%d",&t);   for(int nn=1;nn<=t;nn++)   {       scanf("%d",&n);       for(int i=1;i<=n;i++)            scanf("%lf%lf",&inf[i].xi,&inf[i].hi);       sort(inf+1,inf+n+1,cmp1);       scanf("%d",&q);       for(int i=1;i<=q;i++)       {           scanf("%lf",&sa[i].xi);           be[i]=sa[i].xi;           sa[i].pos=i;       }       sort(sa+1,sa+q+1,cmp2);       int cnt=0;       int la=1;       for(int i=1;i<=q;i++)       {           while(inf[la].xi<sa[i].xi&&la<=n)           {               if(!cnt)               {                   sta[++cnt]=la;                   la++;               }               else if(cnt==1)               {                   if(inf[la].hi>=inf[sta[cnt]].hi)                        sta[cnt]=la;                   else                        sta[++cnt]=la;                   la++;               }               else               {                   int top=sta[cnt];                   int topp=sta[cnt-1];                   while(inf[top].hi<=inf[la].hi||iscan(top,topp,la))                   {                       --cnt;                       if(cnt<=1)                           break;                       top=sta[cnt];                       topp=sta[cnt-1];                   }                   if(cnt<=1)                   {                       if(!cnt)                            sta[++cnt]=la;                       else                       {                           if(inf[la].hi>=inf[sta[cnt]].hi)                                sta[cnt]=la;                           else                                sta[++cnt]=la;                       }                   }                   else                       sta[++cnt]=la;                   ++la;               }           }           if(cnt==1) //最少有一个           {               L[sa[i].pos]=sta[cnt];               continue;           }           int top=sta[cnt];           int topp=sta[cnt-1];           while((inf[top].hi/(sa[i].xi-inf[top].xi))<=((inf[topp].hi-inf[top].hi)/(inf[top].xi-inf[topp].xi)))           {               cnt--;               if(cnt<=1)                    break;               top=sta[cnt];               topp=sta[cnt-1];           }           L[sa[i].pos]=sta[cnt];       }       cnt=0;       la=n;       for(int i=q;i>=1;i--)       {           while(inf[la].xi>sa[i].xi&&la>=1)           {               if(!cnt)               {                   sta[++cnt]=la;                   la--;               }               else if(cnt==1)               {                   if(inf[la].hi>=inf[sta[cnt]].hi)                        sta[cnt]=la;                   else                        sta[++cnt]=la;                   la--;               }               else               {                   int top=sta[cnt];                   int topp=sta[cnt-1];                   while(inf[top].hi<=inf[la].hi||iscan1(top,topp,la))                   {                       --cnt;                       if(cnt<=1)                           break;                       top=sta[cnt];                       topp=sta[cnt-1];                   }                   if(cnt<=1)                   {                       if(!cnt)                            sta[++cnt]=la;                       else                       {                           if(inf[la].hi>=inf[sta[cnt]].hi)                                sta[cnt]=la;                           else                                sta[++cnt]=la;                       }                   }                   else                       sta[++cnt]=la;                   la--;               }           }           if(cnt==1) //最少有一个           {               R[sa[i].pos]=sta[cnt];               continue;           }           int top=sta[cnt],topp=sta[cnt-1];           while((inf[top].hi/(inf[top].xi-sa[i].xi))<((inf[topp].hi-inf[top].hi)/(inf[topp].xi-inf[top].xi)))           {               cnt--;               if(cnt<=1)                    break;               top=sta[cnt];               topp=sta[cnt-1];           }           R[sa[i].pos]=sta[cnt];       }       printf("Case #%d:\n",nn);       for(int i=1;i<=q;i++)       {           int ri=R[i],le=L[i];           //printf("le:%d ri:%d\n",le,ri);           double px=inf[ri].xi-be[i],py=inf[ri].hi;           double qx=inf[le].xi-be[i],qy=inf[le].hi;           double temp=px*qx+py*qy;           printf("%.10f\n",acos(temp/(sqrt(px*px+py*py)*sqrt(qx*qx+qy*qy)))/PI*180.0);       }   }    return 0;}<span style="color:#ff0000;"></span>

05 hdu 5036 Explosion

题目意思:

有n扇门,每扇门里面有一些开其他门的钥匙,如果所有的门都不能开,需要炸开一些门,求把所有的门打开需要炸弹个数的期望。

解题思路:

首先要把问题给抽象出来。然后用位来处理加快速度。一个整数32位,这样1000的数据量用位来处理相当于1000/32的数据量。

考虑每个点需要用炸弹打开的概率,那么所有点的概率之和就是解。每个点 v 需要用炸弹打开的概率是 1/S, S是u(u->v联通)的数量,然后就变成求这个图的传递闭包了,用bitset优化。为什么是1/S呢,因为这S个门里面必定要用一个炸弹砸开,而砸v的概率为1/S。

代码:

//#include<CSpreadSheet.h>#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#include<cmath>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 1100bitset<Maxn>myb[Maxn]; //myb[i]表示i能开的门int n;double solve(){    double ans=0;    for(int i=1;i<=n;i++) //    {        for(int j=1;j<=n;j++)  //用1000个bit处理时间相当于1000/32个整数        {            if(myb[j][i])  //j能开i                myb[j]|=myb[i];  //则j能开的门数要加上i能开的门苏        }    }    for(int i=1;i<=n;i++)    {        int nu=0;        for(int j=1;j<=n;j++)            if(myb[j][i])                nu++;        ans+=1.0/nu;    }    return ans;}int main(){    //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);     int t,cnt=0;     scanf("%d",&t);     while(t--)     {         scanf("%d",&n);         for(int i=1;i<=n;i++)         {             myb[i].reset();             myb[i][i]=1; //自己可以开自己         }         for(int i=1;i<=n;i++)         {             int nu;             scanf("%d",&nu);             for(int j=1;j<=nu;j++)             {                 int temp;                 scanf("%d",&temp);                 myb[i][temp]=1;             }         }         printf("Case #%d: %.5f\n",++cnt,solve());     }    return 0;}


06 hdu 5037 Frog

题目意思:

一只青蛙想到距离为m的河对岸去,河中间有n块石头,告诉每块石头的位置,青蛙每次最多只能跳l距离,求怎样放石头,使得青蛙跳到对岸的步数最大,求这个步数。

解题思路:

贪心

注意青蛙肯定是每次尽可能跳,能跳远的肯定不会跳近的。尽可能的放置l+1的连续三块石头,这样青蛙两步只能走l+1.

代码:

//#include<CSpreadSheet.h>#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#include<cmath>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 220000int sa[Maxn];int n,m,l;int main(){    //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);   int t;   scanf("%d",&t);   for(int cnt=1;cnt<=t;cnt++)   {       scanf("%d%d%d",&n,&m,&l);       for(int i=1;i<=n;i++)            scanf("%d",&sa[i]);       sort(sa+1,sa+n+1);       n=unique(sa+1,sa+n+1)-sa-1;       sa[++n]=m;       int la=l,ans=0;       sa[0]=0;       for(int i=1;i<=n;i++)       {           ans+=(sa[i]-sa[i-1])/(l+1)*2;           int mod=(sa[i]-sa[i-1])%(l+1);           if(mod+la>=l+1)           {               ans++;               la=mod;           }           else               la+=mod;       }       printf("Case #%d: %d\n",cnt,ans);   }    return 0;}/*0 4 35 14 22 2 2 9 51 10 521 7 52*/


07 hdu 5038 Grade

题目意思:

求出现次数最多的那个数。如果所有数出现次数都一样且不是全部一样,则输出Bad Mushroom

解题思路:

水题,排序就行。

代码:

</pre><pre name="code" class="cpp">//#include<CSpreadSheet.h>#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#include<cmath>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 1100000int sa[Maxn],n;struct Inf{    int va,ti;}inf[Maxn];int nu;bool cmp(struct Inf a,struct Inf b){    if(a.ti!=b.ti)        return a.ti>b.ti;    return a.va<b.va;}int main(){    //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);    int t;    scanf("%d",&t);    for(int cnt=1;cnt<=t;cnt++)    {        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            int temp;            scanf("%d",&temp);            sa[i]=10000-(100-temp)*(100-temp);        }        sort(sa+1,sa+n+1);        nu=0;        inf[++nu].va=sa[1];        inf[nu].ti=1;        int la=sa[1];        for(int i=2;i<=n;i++)        {            if(sa[i]==la)            {                inf[nu].ti++;                la=sa[i];            }            else            {                ++nu;                inf[nu].va=sa[i];                inf[nu].ti=1;                la=sa[i];            }        }        sort(inf+1,inf+nu+1,cmp);        printf("Case #%d:\n",cnt);        if(inf[nu].ti==inf[1].ti&&nu!=1)        {            printf("Bad Mushroom\n");            continue;        }        int ti=inf[1].ti;        printf("%d",inf[1].va);        for(int i=2;i<=nu&&inf[i].ti==ti;i++)            printf(" %d",inf[i].va);        putchar('\n');    }    return 0;}

09 hdu 5040 Instrusive

题目意思:

在n*n的格子里,有标有方向的摄像机,摄像机能辐射出去一个格子(包括自己共两个格子,坑点),摄像机每秒钟顺时针旋转90度。‘#’不能走,‘.'可以走。求从’M'到‘T'的最短时间。如果此刻被照或此刻下一格子被照,则到下一格子需花费三秒,否则花费一秒。

解题思路:

BFS

预处理出lig[Maxn][Maxn][5]; //lig[x][y][i]表示格子(x,y)在4*i秒时是否照亮

vis[Maxn][Maxn][5]; //vis[x][y][i]表示格子(x,y)在4*i秒时是否被访问了

然后就是裸地BFS了,按时间优先。

码:

//#include<CSpreadSheet.h>#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#include<cmath>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 550char sa[Maxn][Maxn];bool lig[Maxn][Maxn][5]; //lig[x][y][i]表示格子(x,y)在4*i秒时是否照亮int n,dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};int bx,by,ex,ey,vis[Maxn][Maxn][5]; //vis[x][y][i]表示格子(x,y)在4*i秒时是否被访问了struct Inf{    int x,y;    int ti;    friend bool operator < (Inf a,Inf b)  //时间优先    {        return a.ti>b.ti;    }};bool iscan(int x,int y){    if(x<1||x>n||y<1||y>n)        return false;    return true;}int jud(char c) //判断方向{    if(c=='N')        return 0;    if(c=='E')        return 1;    if(c=='S')        return 2;    if(c=='W')        return 3;    return -1;}int bfs(){    priority_queue<Inf>myq;    Inf st;    st.x=bx,st.y=by,st.ti=0;    vis[st.x][st.y][0]=true;    myq.push(st);    while(!myq.empty())    {        Inf cur;        cur=myq.top();        myq.pop();        //printf("x:%d y:%d ti:%d\n",cur.x,cur.y,cur.ti);        if(cur.x==ex&&cur.y==ey)            return cur.ti;        bool fl=lig[cur.x][cur.y][cur.ti%4];        if(!vis[cur.x][cur.y][(cur.ti+1)%4]) //停一秒        {            Inf ne=cur;            ne.ti+=1;            vis[ne.x][ne.y][ne.ti%4]=true;            myq.push(ne);        }        for(int i=0;i<4;i++)        {            int x=cur.x+dir[i][0],y=cur.y+dir[i][1];            if(!iscan(x,y)||sa[x][y]=='#')                continue;            Inf ne;            ne.x=x,ne.y=y,ne.ti=(fl||lig[x][y][cur.ti%4])?(cur.ti+3):(cur.ti+1);//看是走3秒还是一秒            if(vis[x][y][ne.ti%4])                continue;            vis[x][y][ne.ti%4]=true;            myq.push(ne);        }    }    return -1;}int main(){    //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);   int t;   scanf("%d",&t);   for(int cnt=1;cnt<=t;cnt++)   {       scanf("%d",&n);       memset(lig,false,sizeof(lig));       memset(vis,false,sizeof(vis));       for(int i=1;i<=n;i++)       {           scanf("%s",sa[i]+1);           for(int j=1;j<=n;j++)           {               if(sa[i][j]=='M')               {                   bx=i,by=j;                   continue;               }               if(sa[i][j]=='T')               {                   ex=i,ey=j;                   continue;               }               int du=jud(sa[i][j]);               if(du==-1)                    continue;               for(int k=0;k<4;k++) //初始化格子被照亮情况               {                   lig[i][j][k]=true;                   int x=i,y=j;                   x+=dir[du][0],y+=dir[du][1];                   if(!iscan(x,y))                        break;                   lig[x][y][k]=true;                   du=(du+1)%4;               }           }       }       printf("Case #%d: %d\n",cnt,bfs());   }    return 0;}








0 0