zoukankan      html  css  js  c++  java
  • [SCOI2009]围豆豆

    Description

    Input

    第一行两个整数N和M,为矩阵的边长。 第二行一个整数D,为豆子的总个数。 第三行包含D个整数V1到VD,分别为每颗豆子的分值。 接着N行有一个N×M的字符矩阵来描述游戏矩阵状态,0表示空格,#表示障碍物。而数字1到9分别表示对应编号的豆子。

    Output

    仅包含一个整数,为最高可能获得的分值。

    Sample Input

    3 8
    3
    30 -100 30
    00000000
    010203#0
    00000000

    Sample Output

    38

    HINT

    50%的数据满足1≤D≤3。
    100%的数据满足1≤D≤9,1≤N, M≤10,-10000≤Vi≤10000。

    这个博客有详细图片和解析

    http://blog.csdn.net/Phenix_2015/article/details/50739989

    问题在于如何判断一个豆子是否在多边形内。

    实际上有一个很好判断的方法,那就是可以引一条水平射线,看和多边形有几个交点,有奇数个交点就在多边形内,否则在多边形外。

    这样状态压缩,对于一个状态,肯定步数越少越好,然后就可以更据压缩的状态,做分层图最短路

    每走一步就可以更新当前状态

    但还有一种情况,在偶数个交点时也有可能被围起来。

    如下图所示:

    特殊情况

    那么转移的过程中,显然水平方向的移动是不影响答案的,只有竖直方向的移动才会影响到点的位置

    特殊情况把每一条线段假设成上端为开下端为闭的线段,即只有下断点与射线相交才会有用,那么这样同向的线段就只会被算一次了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 struct ZYYS
     9 {
    10   int x,y,s;
    11 };
    12 const int dx[4]={0,0,1,-1};
    13 const int dy[4]={1,-1,0,0};
    14 int d,px[101],py[101],n,m,val[11],ans;
    15 int dist[11][11][513],inf;
    16 bool vis[11][11][513];
    17 char ss[11][11];
    18 int cross(int sx,int sy,int x,int y,int s)
    19 {int i;
    20   int p=max(sy,y);
    21   for (i=1;i<=d;i++)
    22     if (py[i]==p&&px[i]<x)
    23       s^=(1<<i-1);
    24   return s;
    25 }
    26 void spfa(int sx,int sy)
    27 {int i,j;
    28   queue<ZYYS>Q;
    29   memset(dist,127/2,sizeof(dist));
    30   inf=dist[0][0][0];
    31   memset(vis,0,sizeof(vis));
    32   Q.push((ZYYS){sx,sy,0});
    33   dist[sx][sy][0]=0;
    34   while (Q.empty()==0)
    35     {
    36       ZYYS u=Q.front();
    37       Q.pop();
    38       vis[u.x][u.y][u.s]=0;
    39       for (i=0;i<4;i++)
    40     {
    41       int x=u.x+dx[i],y=u.y+dy[i];
    42       if (x<1||x>n||y<1||y>m) continue;
    43       if (ss[x][y]=='#'||ss[x][y]!='0') continue;
    44       int s=u.s;
    45       if (i<=1)
    46         s=cross(u.x,u.y,x,y,s);
    47       if (dist[x][y][s]>dist[u.x][u.y][u.s]+1)
    48         {
    49           dist[x][y][s]=dist[u.x][u.y][u.s]+1;
    50           if (vis[x][y][s]==0)
    51         {
    52           vis[x][y][s]=1;
    53           Q.push((ZYYS){x,y,s});
    54         }
    55         }
    56     }
    57     }
    58   for (i=0;i<=(1<<d)-1;i++)
    59     {
    60       int res=-dist[sx][sy][i];
    61       for (j=1;j<=d;j++)
    62     if (i&(1<<j-1)) res+=val[j];
    63       ans=max(ans,res);
    64     }
    65 }
    66 int main()
    67 {int i,j;
    68   cin>>n>>m>>d;
    69   for (i=1;i<=d;i++)
    70     {
    71       scanf("%d",&val[i]);
    72     }
    73   for (i=1;i<=n;i++)
    74     {
    75       scanf("%s",ss[i]+1);
    76       for (j=1;j<=m;j++)
    77     {
    78       if (ss[i][j]>'0'&&ss[i][j]<='9')
    79         px[ss[i][j]-'0']=i,py[ss[i][j]-'0']=j;
    80     }
    81     }
    82   for (i=1;i<=n;i++)
    83     {
    84       for (j=1;j<=m;j++)
    85     if (ss[i][j]=='0')
    86     {
    87       spfa(i,j);
    88     }
    89     }
    90   cout<<ans;
    91 }
  • 相关阅读:
    文件操作函数
    sublime text2 常用快捷键
    过滤掉字段为空的数据
    PHP安装memcache扩展接口步骤
    大数据的逻辑,其实是中医的逻辑
    大数据的逻辑,其实是中医的逻辑
    SPSS输出结果如何在word中设置小数点前面显示加0
    SPSS输出结果如何在word中设置小数点前面显示加0
    掌握4个有效的数据分析要点,切实解决用户痛点
    掌握4个有效的数据分析要点,切实解决用户痛点
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8277741.html
Copyright © 2011-2022 走看看