bzoj1007: [HNOI2008]水平可见直线
Posted Nico&11101001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1007: [HNOI2008]水平可见直线相关的知识,希望对你有一定的参考价值。
题目链接
题解
显然,维护一个下凸壳(是这么叫吧)
按斜率小及大排序
引入直线啊
令直线a斜率小与等于直线b时
令a挡住b
那么a与b之前相交的直线c的交点必然在b与c交点的左边
这样a与b的交点才会在直线c的左边
用单调栈维护
斜率与截距都相同时要unique...另外,有些卡精度.....
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-' ) f = -1;c = getchar();}
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f;
}
const int maxn = 11;
int n,m;
int D,val[maxn];
int map[maxn][maxn],fs[6] = {1,0,-1,0,1} ;
char a[maxn];
int dp[maxn][maxn][1 << maxn];
int ans = 0;
struct Node {
int x,y,S;
Node(int x = 0,int y = 0,int S = 0) : x (x),y(y),S(S) {};
}loc[maxn * maxn];
//inline int Get_Node(int i ,int j) { return i * (n - 1) + j; }
int Get_Point(int x,int y,int tx,int ty,int S) {
for(int i = 0;i < D;++ i) {
int X = loc[i].x,Y = loc[i].y;
if(((x < X && tx >= X) || (x >= X && tx < X)) && y > Y)
S ^= (1<<i);
}
return S;
}
void spfa(int I,int J) {
memset(dp,0x3f,sizeof dp);
std::queue<Node>que;que.push(Node(I,J,0));
dp[I][J][0] = 0;
while(! que.empty()) {
Node cur = que.front();que.pop();
for(int j = 0;j < 4;++ j) {
int tx = cur.x + fs[j],
ty = cur.y + fs[j + 1];
if(tx > n || tx < 1 || ty > m || ty < 1 || map[tx][ty] != -1) continue;
int state = Get_Point(cur.x,cur.y,tx,ty,cur.S);
//printf("%d\n",state);
if(dp[tx][ty][state] > dp[cur.x][cur.y][cur.S] + 1) {
dp[tx][ty][state] = dp[cur.x][cur.y][cur.S] + 1;
que.push(Node(tx,ty,state)) ;
}
}
}
for(int i = 0;i < (1<<D); ++ i) {
int V = -dp[I][J][i];
for(int j = 0;j < D;++ j) {
if((1 << j) & i) V += val[j];
}
ans = std::max(ans,V);
}
}
int main() {
n = read(),m = read();D = read();
for(int i = 0;i < D;++ i) val[i] = read();
for(int i = 1;i <= n;++ i) {
scanf("%s",a + 1);
for(int j = 1;j <= m;++ j) {
if(a[j] >= '0' && a[j] <= '9') { map[i][j] = a[j] - '0' - 1;loc[map[i][j]] = Node(i,j,0); }
else if(a[j] == '#') map[i][j] = 13;
else map[i][j] = -1;
}
}
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= m;++ j)
if(map[i][j] == -1) spfa(i,j);
printf("%d\n",ans);
return 0;
}
以上是关于bzoj1007: [HNOI2008]水平可见直线的主要内容,如果未能解决你的问题,请参考以下文章