CF375C Circling Round Treasures

1|0CF375C Circling Round Treasures

1|1题目链接:

Link

1|2题目分析:

首先看到这个题先想状压吧,但是我因为 sb T2 调的时间太长了并没有仔细想这个东西,发现并不是那么难?

首先看到宝藏和陷阱的和是小于 8 的,直接想状压。而且数据范围又极小,所以我们可以直接设 dp[i][j][s] 表示在 (i,j) 这个点,所包括的宝藏的状态是 S 的最小步数。

状态并不是很难想,但是问题是如何满足题目里所要求的条件。首先,对于一些陷阱,我们可以直接把它看成宝藏,只不过他的价值是负的极大值,所以我们选的时候最优的情况一定不会包括陷阱。那么就剩下了一个问题,如何判断是否在所走的这个多边形里面。

我们对于每一个宝藏只考虑从这个点竖着发出的射线,这样的话,只有走横向边的时候才会奇偶性发生改变。走竖向边的时候不用管,这样的话我们把这个线段看成是左开右闭的,然后直接判断即可。利用 bfs 进行转移。

1|3Code:

//editor : DRYAYST //Wo shi ge da SHA BI #include<bits/stdc++.h> #define g() getchar() #define il inline #define ull unsigned long long #define eps 1e-10 #define ll long long #define pa pair<int, int> #define for_1(i, n) for(int i = 1; i <= (n); ++i) #define for_0(i, n) for(int i = 0; i < (n); ++i) #define for_xy(i, x, y) for(int i = (x); i <= (y); ++i) #define for_yx(i, y, x) for(int i = (y); i >= (x); --i) #define for_edge(i, x) for(int i = head[x]; i; i = nxt[i]) #define int long long #define DB double #define ls (p<<1) #define rs (p<<1|1) #define m_p make_pair #define fi first #define se second using namespace std; const int N = 1e6 + 10, INF = 150000, mod = 1e9 + 7; il int qpow(int x, int k) {int ans = 1; while(k) {if(k & 1) ans = ans * x % mod; x = x * x % mod; k >>= 1; } return ans; } inline int re() { int x = 0, p = 1; char ch = getchar(); while(ch > '9' || ch < '0') {if(ch == '-') p = -1; ch = getchar();} while(ch <= '9' and ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();} return x * p; } int n, m, sx, sy, tot; char S[30][30]; int a[30], b[30], val[30], sum[300], dp[30][30][300]; int dx[5] = {0, 0, 0, 1, -1}, dy[5] = {0, 1, -1, 0, 0}; struct Node{ int x, y, s; }; queue<Node> q; il bool In(int nowx, int nowy, int nx, int ny, int id) { if(nx == a[id] and ny < b[id]) if(nowx < nx) return 1; if(nowx == a[id] and nowy < b[id]) if(nowx > nx) return 1; return 0; } il int bfs() { while (q.size()) q.pop(); memset(dp, -1, sizeof(dp)); q.push(Node{sx, sy, 0}); dp[sx][sy][0] = 0; int ans = 0; while(q.size()) { int x = q.front().x, y = q.front().y, s = q.front().s; q.pop(); // cout<<"x = "<<x<<" y = "<<y<<endl; if(x == sx and y == sy) {ans = max(ans, sum[s] - dp[x][y][s]);} for(int i = 1; i <= 4; ++i) { int nx = x + dx[i], ny = y + dy[i]; if(nx <= 0 || nx > n || ny <= 0 || ny > m || (S[nx][ny] != '.' and S[nx][ny] != 'S') ) continue; int ns = s; for(int j = 1; j <= tot; ++j) if(In(x, y, nx, ny, j)) ns ^= (1 << (j - 1)); if(dp[nx][ny][ns] == -1) {dp[nx][ny][ns] = dp[x][y][s] + 1; q.push(Node{nx, ny, ns}); } } } return ans; } signed main() { // freopen("land.in","r",stdin); freopen("land.out","w",stout); n = re(), m = re(); for_1(i, n) scanf("%s", S[i] + 1); for_1(i, n) { for_1(j, m) { char ch = S[i][j]; if(ch == 'S') sx = i, sy = j; else if(ch != '.' and ch != 'B' and ch != '#') {a[ch - 48] = i, b[ch - 48] = j; ++tot; } } } for_1(i, tot) val[i] = re(); for_1(i, n) for_1(j, m) {if(S[i][j] == 'B') {a[++tot] = i, b[tot] = j, val[tot] = -INF; }} for(int st = 1; st < (1<<tot); ++st) {for_1(i, tot) if((st>>(i-1))&1) sum[st] += val[i];} int ans = bfs(); printf("%lld\n", ans); } /* 4 4 .... .S1. .... .... 10 */

__EOF__

本文作者Zwaire
本文链接https://www.cnblogs.com/Zwaire/p/16117515.html
关于博主:这个世界除了你,都知道我喜欢你
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Zwaire  阅读(27)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示