hdu 3468 Treasure Hunting

二分图匹配

题意: 。。。 看了半天

我们可以从rally点出发到最近的rally点, 如果有treasure在这两个rally点的最短路径上, 我们可以拿走他。

思路也可以参见http://blog.csdn.net/wall_f/article/details/8990937

这种分析问题的思路太值得学习了。。

一开始没看懂题。。 在vj上找了个代码 (o(╯□╰)o。。 谴责一下自己。。)然后写了一下注释。。

写完注释发现就那么回事 不想再敲一遍了。。噗。。

  1 /*Author :usedrose  */
  2 /*Created Time :2015/8/3 21:00:00*/
  3 /*File Name :2.cpp*/
  4 #pragma comment(linker, "/STACK:1024000000,1024000000")
  5 #include <cstdio>
  6 #include <iostream>
  7 #include <algorithm>
  8 #include <sstream>
  9 #include <cstdlib>
 10 #include <cstring>
 11 #include <climits>
 12 #include <vector>
 13 #include <string>
 14 #include <ctime>
 15 #include <cmath>
 16 #include <deque>
 17 #include <queue>
 18 #include <stack>
 19 #include <set>
 20 #include <map>
 21 #define INF 0x3f3f3f3f
 22 #define eps 1e-8
 23 #define pi acos(-1.0)
 24 #define MAXN 1110
 25 #define MAXM 100110
 26 #define OK cout << "ok" << endl;
 27 #define o(a) cout << #a << " = " << a << endl
 28 #define o1(a,b) cout << #a << " = " << a << "  " << #b << " = " << b << endl
 29 using namespace std;
 30 typedef long long LL;
 31
 32 int vv[MAXM], nxt[MAXM], h[MAXN*MAXN], e;
 33 char str[MAXN][MAXN];
 34 int n, m;
 35 int dis[55][MAXN*MAXN];
 36 int d[MAXN][MAXN];
 37 int bx[MAXN], by[MAXN];
 38
 39 void addedge(int u,int v)
 40 {
 41     vv[e] = v;
 42     nxt[e] = h[u];
 43     h[u] = e++;
 44 }
 45
 46 int vis[MAXN*MAXN], pre[MAXN*MAXN];
 47 int dx[] = {0, 0, 1, -1};
 48 int dy[] = {1, -1, 0, 0};
 49
 50 int getid(char x)
 51 {
 52     if (isupper(x)) return x - ‘A‘;
 53     if (islower(x)) return x - ‘a‘ + 26;
 54     if (x == ‘*‘) return -1;
 55     return -2;
 56 }
 57
 58 int getid(int x, int y)
 59 {
 60     return x*m + y;
 61 }
 62
 63 bool inside(int x, int y)
 64 {
 65     return x >= 0 && x < n && y >= 0 && y < m;
 66 }
 67
 68
 69 void bfs(int x, int y)
 70 {
 71     queue<int> q;
 72     memset(d, -1, sizeof(d));
 73     q.push(x), q.push(y);
 74     d[x][y] = 0;
 75     while (!q.empty()) {
 76         x = q.front(); q.pop();
 77         y = q.front(); q.pop();
 78         for (int i = 0;i < 4; ++ i) {
 79             int x1 = x + dx[i];
 80             int y1 = y + dy[i];
 81             if (inside(x1, y1) && str[x1][y1] != ‘#‘ && d[x1][y1] < 0) {
 82                 d[x1][y1] = d[x][y] + 1;
 83                 q.push(x1); q.push(y1);
 84             }
 85         }
 86     }
 87 }
 88
 89 bool init()
 90 {
 91     memset(bx, -1, sizeof(bx));
 92     for (int i = 0;i < n; ++ i)
 93         for (int j = 0;j < m;++ j) {
 94             int x = getid(str[i][j]);
 95             if (x >= 0) {                // if it is a rally point
 96                 bx[x] = i, by[x] = j;     //note its position
 97                 bfs(i, j);                // get the shortest path around it
 98                 for (int k = 0;k < n; ++ k)
 99                     for (int l = 0;l < m; ++ l) {
100                         dis[x][k*m+l] = d[k][l];    // get the distances from the point to all nodes
101                         if (getid(str[k][l]) >= 0 && d[k][l] == -1) return false;// if unreachable
102                     }
103             }
104         }
105     for (int i = 0;i < n; ++ i)
106         for (int j = 0;j < m; ++ j) if (str[i][j] == ‘*‘) { // for all treasure
107             for (int k = 1;bx[k] != -1; ++ k) {// for all rally points
108                 if (dis[k-1][i*m+j] + dis[k][i*m+j] == dis[k-1][getid(bx[k],by[k])]) // if treasure on the shortest path between two rallys
109                     if (dis[k-1][i*m+j] != -1 && dis[k][i*m+j] != -1)
110                         addedge(k, i*m+j);            //we should add an edge
111             }
112         }
113     return true;
114 }
115
116 int dfs(int u)
117 {
118     for (int i = h[u]; i + 1;i = nxt[i]) {
119         int v = vv[i];
120         if (vis[v]) continue;
121         vis[v] = 1;
122         if (pre[v] == -1 || dfs(pre[v])) {
123             pre[v] = u;
124             return 1;
125         }
126     }
127     return 0;
128 }
129
130 int solve()
131 {
132     if (!init()) return -1;
133     int ans = 0;
134     memset(pre, -1, sizeof(pre));
135     for (int i = 1; bx[i] != -1;++ i) {
136         memset(vis, 0 ,sizeof(vis));
137         ans += dfs(i);
138     }
139     return ans;
140 }
141
142 int main()
143 {
144     while (cin >> n >> m) {
145         memset(h, -1, sizeof(h));
146         e = 0;
147         for (int i = 0;i < n; ++ i)
148             cin >> str[i];
149         cout << solve() << endl;
150     }
151     return 0;
152 }
时间: 2024-11-07 17:12:14

hdu 3468 Treasure Hunting的相关文章

HDU 3468 Treasure Hunting(BFS+网络流之最大流)

题目地址:HDU 3468 这道题的关键在于能想到用网络流.然后还要想到用bfs来标记最短路中的点. 首先标记方法是,对每一个集合点跑一次bfs,记录所有点到该点的最短距离.然后对于任意一对起始点来说,只要这个点到起点的最短距离+该点到终点的最短距离==起点到终点的最短距离,就说明这点在某条从起点到终点的最短路上. 然后以集合点建X集,宝物点建Y集构造二分图,将从某集合点出发的最短路中经过宝物点与该集合点连边.剩下的用二分匹配算法或最大流算法都可以.(为什么我的最大流比二分匹配跑的还要快....

HDU 3468 Treasure Hunting (最大流SAP)经典(看似广搜实则最大流)

Treasure Hunting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 1532    Accepted Submission(s): 400 Problem Description Do you like treasure hunting? Today, with one of his friend, iSea is on

【网络流】 HDU 3468 Treasure Hunting

题意: A-Z&&a-z 表示 集结点 从A点出发经过 最短步数 走到下一个集结点(A的下一个集结点为B ,Z的下一个集结点为a) 的路上遇到金子(*)则可以捡走(一个点只能捡一次) 求从A点出发走遍所有的的集结点 最多能捡多少金子 思路:先对于第 i 个集结点用BFS求出 对于每个点从该集结点所需的步数  为D[ I ] [ t ] 对于任意一个金子若  两个相邻的集结点的最短步数=其到该金子的步数和 则建一条边(可以拿) 然后最大流求 #include <cstdio> #

hdu 3641 Treasure Hunting 强大的二分

1 /** 2 大意:给定一组ai,bi . m = a1^b1 *a2^b2 * a3^ b3 * a4^b4*...*ai^bi 3 求最小的x!%m =0 4 思路: 将ai 质因子分解,若是x!%m=0 那么x! 质因子分解之后 质因子的个数一定大于等于m的个数.二分求解可得 5 注意: 二分时,需要将,上下限 设定好,low =0: high = 1ll<<60; 6 **/ 7 8 #include <iostream> 9 #include <cstring&g

HDU 3641 Treasure Hunting (素数拆分)

题意:有N个ai,bi,M=a1^b1*a2^b2*a3^b3-*an^bn ,求最小的 x 使得 x! % M ==0. 思路:把M分成多个素数相乘,num[i] 记录素数 i 的个数,然后二分找到x,若 x! 中所有 i 的个数满足>=num[i] 即为答案. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #in

HDU 3641 Treasure Hunting

用二分查找来找到一个X使得满足X!%M==0 M=a1^b1*a2^b2*a3^b3-*an^bn X!=1*2*3*4*5....*X; M可以化为其个个质因子的k次方的乘积 例如 2^3*3^2*4^5==2^13*3^2; X!则可以得到 例如 2的次方为 X! = 2^(X/2)*(1*2*3*4*5*6*7....*X/2)*other=(x/2)! *other; 继续计算知道x/2==1为止 得到次方数:再与输入的数比较 输入的ai,bi 计算并储存好个个质数的次方 #includ

HDU 3641 Treasure Hunting (二分+分解质因子)

题目链接:HDU 3641 Treasure Hunting 题意:求X!%M==0中最小的的X.其中M=a1^b1*a2^b2*a3^b3.... 思路:求余为0想到整除,即分母的因子构成的集合是分子的因子构成的集合的子集.因子又想到,任何一个整数都可以分解成若干个素数相乘. 注意:题目数据很大,查到答案时二分. AC代码: #include<stdio.h> #include<string.h> #define ll __int64 bool Prime[210]; ll nu

HDU 3641 Treasure Hunting(阶乘素因子分解+二分)

题目链接:传送门 题意: 求最小的 ( x! ) = 0 mod (a1^b1*a2^b2...an^bn) 分析: 首先吧a1~an进行素因子分解,然后统计下每个质因子的指数,由于随着x的增大,质因子的个数是逐渐增加的 因此我们可以二分x,对x!进行素因子分解判断是否满足条件,然后求出最小的就可以了. 代码如下: #include <iostream> #include <cstring> #include <algorithm> #include <cstdi

Treasure Hunting (hdu 3468 二分匹配+bfs最短路径)

Treasure Hunting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 1509    Accepted Submission(s): 393 Problem Description Do you like treasure hunting? Today, with one of his friend, iSea is on