[2014 北京网络赛]

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 110000

struct 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 1100
bitset<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 220000

int 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 3
5 14 2
2 2 2 9 5
1 10 5
2
1 7 5
2
*/





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 1100000
int 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 550

char 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;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值