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

    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

    数据范围:

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

    分析:这个题真是恶心啊。卡了我好几节课。

       题意就不说了……

       ①先来说一下如何判断多边形能否围住豆豆,我们从豆豆向右引一条射线,判断和多边形有几个交点,如果有奇数个说明豆豆在里面。

         但是有可能会出现射线和一条边重合的情况,点是在多边形里的,可这样判断,点是在外面的。

       由于我们是向右引的,我们只需要当物体上下移动的时候判断,这样不会出现重合的情况,豆豆只会跨过多边形的边。

       ②这道题该怎么做?看数据的话很显然是状压dp。定义f[x][y][s]表示从(x,y)出发的点,状态为s(围住了哪几个豆豆),围成的最短的多边形的长度。我们要预处理出来每个状态下围住豆豆的分数v[s]

        从当前的状态如何推得下一个状态?我们需要判断下一个走到下一个格子时,每个豆豆是否还在多边形里面。根据①可以知道豆豆是否还在里面。

        如果改变了,就让状态s的第i位取反,表示豆豆在里面或者不在里面。

        如何得到f[x][y][s]? 我们可以跑bfs或者spfa,由于从起点遍历整个图,路径是可达的,必然可以回到起点。

        最后再求出来v[s]-f[x][y][s]的最大值就行了。

     1 /*************************************************************************
     2     > File Name: s.cpp
     3     > Author: LiuGeXian
     4     > Mail: 1019630230@qq.com 
     5     > Created Time: 2020/4/14 18:47:59
     6  ************************************************************************/
     7 #include <bits/stdc++.h>
     8 const int maxn = 11;
     9 using namespace std;
    10 struct Node{
    11     int x, y, z;
    12     Node(int a, int b, int c){
    13         x = a;
    14         y = b;
    15         z = c;
    16     }
    17 };
    18 int dx[5] = {0, 0, 1, -1};
    19 int dy[5] = {1, -1, 0, 0};
    20 int Max, f[maxn][maxn][1 << maxn], ans = -1, p[maxn];
    21 int d, n, m, g[maxn][maxn], px[maxn], py[maxn], v[1 << maxn], vis[maxn][maxn][1 << maxn];
    22 inline int Jud(int ax,int ay,int bx,int by,int az){
    23     for(int i = 1; i <= d; i++){
    24         if(((ax == px[i] && bx < px[i]) || (ax < px[i] && bx == px[i])) && by>py[i]){
    25             az ^= (1<<(i-1));
    26         }
    27     }
    28     return az;
    29 }
    30 int t;
    31 inline void F(int x, int y){
    32     queue<Node> q;
    33     q.push((Node){x, y, 0});
    34     memset(f, 0x3f, sizeof(f));
    35     memset(vis, 0, sizeof(vis));
    36     f[x][y][0] = 0;
    37     while (q.size()){
    38         int ax = q.front().x;
    39         int ay = q.front().y;
    40         int az = q.front().z;
    41         vis[ax][ay][az] = 0;
    42         q.pop();
    43         for (int k = 0; k < 4; k++){
    44             int bx = ax + dx[k];
    45             int by = ay + dy[k];
    46             int bz = az;
    47             if (bx < 1 || by < 1 || bx > n || by > m) continue;
    48             if (g[bx][by]) continue;
    49             if (k >= 2) bz = Jud(ax, ay, bx, by, az);
    50             if (f[ax][ay][az]+1 < f[bx][by][bz]){
    51                 f[bx][by][bz] = f[ax][ay][az] + 1;
    52                 if (!vis[bx][by][bz])
    53                     vis[bx][by][bz] = 1;
    54                     q.push((Node){bx, by, bz});
    55             }
    56         }
    57     }
    58     for (int s = 0; s < Max; s++){
    59         ans = max(ans, v[s] - f[x][y][s]);
    60     }
    61 }
    62 int main(){
    63     scanf("%d%d", &n, &m);
    64     scanf("%d", &d);
    65     Max = 1 << d;
    66     for (int i = 1; i <= d; i++) scanf("%d", &p[i]);
    67     for (int i = 0; i < Max; i++){
    68         for (int j = 1; j <= d; j++){
    69             if (i &(1 << (j-1))) v[i] += p[j];
    70         }
    71     }
    72     for (int i = 1; i <= n; i++){
    73         for (int j = 1; j <= m; j++){
    74             char ch;
    75             scanf(" %c", &ch);
    76             if (ch == '#') g[i][j] = -1;
    77             else if (ch == '0') g[i][j] = 0;
    78             else {
    79                 int num = ch - '0';
    80                 g[i][j] = num;
    81                 px[num] = i;
    82                 py[num] = j;
    83             }
    84         }
    85     }
    86     for (int i = 1; i <= n; i++){
    87         for (int j = 1; j <= m; j++){
    88             if (!g[i][j]) F(i, j); 
    89         }
    90     }
    91     cout << ans;
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    getchar()详解
    ACM错误提示
    关于printf()函数和浮点数
    PCB蚀刻,盐酸不好买,三氯化铁不方便,用这个吧【转】
    wps自动半角符转全角符取消笔记
    万恶的oj笔记之【111028】
    hdu1142 深搜+dp+最短路径。
    pl2303电路图。。
    sencha touch 监控 Carousel 旋转事件
    正则表达式限制文本框输入内容
  • 原文地址:https://www.cnblogs.com/ghosh/p/12710191.html
Copyright © 2011-2022 走看看