BZOJ 1294 [SCOI2009]围豆豆Bean ——计算几何

显然我们不可能表示出一台路径,因为实在是太复杂了。

所以我们可以记录一下路径对答案的影响,显然路径对答案影响相同的时候,答案更优,所以我们可以用影响来代替路径。

所以我们考虑状压一下所有的豆子有没有被围起来,然后判定的方法是随便引出一条射线,判断和多边形的交点的个数,我们只需要记录奇偶性,所以直接状压即可。

然后枚举起点,宽度优先搜索处理之后,计算所有影响下的最优答案即可。

为了方便转移,我们选择豆子向上偏右的方向的射线作为判断。

#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair

int v[10],n,m,d,ret=0;
int dis[11][11][1<<10];
char s[20];
int map[12][12],x[10],y[10];
int mov[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
queue <int> qx,qy,qs;

void print(int x)
{
    F(i,0,d-1) printf("%d",(x>>i)&1);
}

int main()
{
    scanf("%d%d%d",&n,&m,&d);
    F(i,0,d-1) scanf("%d",&v[i]);
    F(i,1,n)
    {
        scanf("%s",s+1);
        F(j,1,m)
        {
            switch(s[j])
            {
                case ‘0‘: map[i][j]=0;break;
                case ‘#‘: map[i][j]=-1;break;
                default:x[s[j]-‘1‘]=i;y[s[j]-‘1‘]=j;map[i][j]=-1;break;
            }
        }
    }
//  F(i,0,d-1) printf("Bean (%d,%d)\n",x[i],y[i]);
    F(i,0,m+1) map[0][i]=map[n+1][i]=-1;
    F(i,0,n+1) map[i][0]=map[i][m+1]=-1;
//  F(i,0,n+1) F(j,0,m+1) printf("%5d%c",map[i][j],j==m+1?‘\n‘:‘ ‘);
    F(sx,1,n) F(sy,1,m)
    {
        memset(dis,0x3f,sizeof dis);
        qx.push(sx);qy.push(sy);qs.push(0);dis[sx][sy][0]=0;
        while (!qx.empty())
        {
            int nx=qx.front(),ny=qy.front(),ns=qs.front();
//          printf("now is %d %d ",nx,ny); print(ns); printf("\n");
            qx.pop();qy.pop();qs.pop();
            if (nx==sx&&ny==sy)
            {
                int ans=-dis[nx][ny][ns];
                F(i,0,d-1) if (ns&(1<<i)) ans+=v[i];
                ret=max(ret,ans);
            }
            F(k,0,3)
            {
                int tx=nx+mov[k][0],ty=ny+mov[k][1];
//              printf("(%d,%d) to (%d,%d) k is %d\n",nx,ny,tx,ty,k);
                if (map[tx][ty]!=-1)
                {
                    int ts=ns;
                    F(i,0,9)
                    {
                        if ((k==0&&(ty==y[i]+1&&tx<x[i]))
                          ||(k==1&&(ty==y[i]&&tx<x[i])))
                            {
//                              printf("go %d\n",i);
                                ts^=1<<i;
                            }
//                      printf("Bea %d %d\n",x[i],y[i]);
                    }
//                  print(ts); printf("\n");
                    if (dis[tx][ty][ts]>dis[nx][ny][ns]+1)
                    {
                        dis[tx][ty][ts]=dis[nx][ny][ns]+1;
                        qx.push(tx);qy.push(ty);qs.push(ts);
                    }
                }
            }
        }
    }
    printf("%d\n",ret);
}

  

时间: 2024-08-08 05:37:18

BZOJ 1294 [SCOI2009]围豆豆Bean ——计算几何的相关文章

bzoj1294: [SCOI2009]围豆豆Bean

题目链接 bzoj1294: [SCOI2009]围豆豆Bean 题解 对豆豆进行装压 令dp[i][j][k]表示从i,j出发,把状态为k豆豆的围起来的最小话费 spfa转移 在进行状态的转移的时候,我们需要得到下一个位置的豆豆状态 利用射线法判断是否在多边形内部,从该豆豆点向右引出一条射线,如果穿过的边界是奇数就算,偶数则不算. 异或记录奇偶转移 #include<queue> #include<cstdio> #include<cstring> #include&

BZOJ 1294 围豆豆Bean(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1294 题意: 思路:f[i][j][st]表示从(i,j)出 发到(i,j)停止组成的回路.状态为st的最小步数.从每个0的位置(i,j)进行BFS一次,得到所有的状态.判断一个路径是否包含某个格子时,可以 从该格子向左发出一条射线,判断这条射线与路径交点个数.为奇数时包含. char s[N][N]; int f[N][N][1<<9]; int a[N],n,m,K; int b

[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——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

BZOJ 1296: [SCOI2009]粉刷匠

BZOJ 1296: [SCOI2009]粉刷匠 Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被粉刷一次. 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷. Input 输入文件paint.in第一行包含三个整数,N M T. 接下来有N行,每行一个长度为M的字符串,

BZOJ 2433 智能车比赛(计算几何+最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2433 题意:若干个矩形排成一排(同一个x之上最多有一个矩形),矩形i和i+1相邻.给定两点S和T,两点均在矩形内.求S到T的最短路径.只能在矩形内部走. 思路:首先,S到T若有转弯,必定是在矩形 的顶点处转弯.因此,只要建立任意两可达顶点(包含S和T)之间距离求最短路即可.若暴力枚举任意两点再判是否可达复杂度O(n^3).优化.枚举起点 a,从左向右扫遍矩形,利用叉积维护关于该点a的上

BZOJ 1024: [SCOI2009]生日快乐 dfs

1024: [SCOI2009]生日快乐 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1024 Description windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕.现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋糕. windy主刀,每一切只能平行于一块蛋糕的一边(任意一边

bzoj 1026 [SCOI2009]windy数(数位DP)

1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4550  Solved: 2039[Submit][Status][Discuss] Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数. Sample

BZOJ 1296: [SCOI2009]粉刷匠 分组DP

1296: [SCOI2009]粉刷匠 Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被粉刷一次. 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷. Input 输入文件paint.in第一行包含三个整数,N M T. 接下来有N行,每行一个长度为M的字符串,'0'表示