G - 7 HDU - 1241
八连块问题——dfs算法
参考// 算法竞赛入门经典(第二版)P163
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 105;
char pic[maxn][maxn];
int m, n, idx[maxn][maxn]; //m,n:行数、列数 ,idx:标记
void dfs(int r, int c, int id)
{
if (r < 0 || r >= m || c < 0 || c >= n) return; //"出界"的格子
if (idx[r][c] > 0 || pic[r][c] != '@') return; //不是"@"或者已经访问过的格子
idx[r][c] = id; //连通分量编号
for (int dr = -1; dr <= 1; ++dr) //遍历八连块
{
for (int dc = -1; dc <= 1; ++dc)
{
if (dr != 0 || dc != 0) dfs(r + dr, c+dc,id); //是'@'则递归
}
}
}
int main()
{
while (cin >> m >> n, m&&n)
{
for (int i = 0; i < m; ++i)
{
for (int t = 0; t < n; ++t)
{
cin >> pic[i][t];
}
}
int cnt = 0;
memset(idx, 0, sizeof(idx));
for (int i = 0; i < m; ++i)
{
for (int t = 0; t < n; ++t)
{
if (idx[i][t] == 0 && pic[i][t] == '@') dfs(i, t, ++cnt);
}
}
cout << cnt <<endl;
}
return 0;
}
H - 8 HDU - 1495
非常可乐(平分水问题/倒水问题)
BFS
#include <iostream>
#include <queue>
#include <cstring> //用来给数组赋初值为0的,memset;
using namespace std;
int b[3], book[101][101][101], half;
struct node
{
int cur[3], s; //◆cur表示现在瓶子里的水,b表示杯子的容量
}p, temp; //p获取当前的“head”,temp用于6个动作的记录。
void bfs()
{
queue<node> q; //声明一个队列
p.cur[0] = b[0]; //测试数据,如果不把之前队列里的数据清空就会带到下一组测试中
p.cur[1] = p.cur[2] = p.s = 0; //放到bfs里面 每次队列都是新的。
q.push(p); //将最开始状态初始化 加入队列q中;
while (!q.empty())
{
p = q.front();
q.pop();
for (int i = 0; i < 3; i++) //控制哪个杯子往外倒水
{
if (p.cur[i] > 0) //如果有水才可以给别的倒水。
{
for (int j = 0; j < 3; j++) //接受水的杯子
{
temp = p; //因为这6个动作是”平行“的,即都是从前一步状态开始的,如果没有这一句,就不是平行的,相互叠加的。
if (i == j) continue; //不能给自己倒水
if (temp.cur[i] > b[j] - temp.cur[j]) //判断能不能倒满了,这是可以倒满的情况
{
temp.cur[i] -= b[j] - temp.cur[j]; //将j杯倒满后i杯有剩余
temp.cur[j] = b[j]; //此时j杯的水量为j杯的容量
}
else // 不可以倒满的情况
{
temp.cur[j] += temp.cur[i];
temp.cur[i] = 0;
}
if (!book[temp.cur[0]][temp.cur[1]][temp.cur[2]]) //判断这种情况是否出现过,理解!!!
{
book[temp.cur[0]][temp.cur[1]][temp.cur[2]] = 1; //标记为出现过,说明这一步“有效”,step+1;
temp.s++;
if ((temp.cur[0] == half && temp.cur[1] == half) || (temp.cur[0] == half && temp.cur[2] == half) || (temp.cur[1] == half && temp.cur[2] == half))
{ //判断达到所要结果,跳出循环
cout << temp.s << endl; // step里的每一个“动作”都要判断是否符合条件,因为这动作是平行的 所以放在内循环里面!
return; //直接跳出bfs
}
q.push(temp);// ▲如果不是所求,就把他加到队列里。之后再从每一个“动作调用”
}
}
}
}
}
cout << "NO" << endl; //■如果整个循环结束还是没有找到,说明不可以平分;
}
int main()
{
while (cin >> b[0] >> b[1] >> b[2], b[0] + b[1] + b[2])
{
memset(book, 0, sizeof(book)); //★多组数据每一组都要赋初值,想用book[][][]={0},必须要在声明book数组时候用;
book[b[0]][b[1]][b[2]] = 1; //☀把初始点标记来过,这一点在调用bfs之前做 很多题都要注意这一点。
if (b[0] % 2) cout << "NO" << endl; //水量为偶数则可平分
else { half = b[0] / 2; bfs(); }
}
return 0;
}