每日算法
those times when you get up early and you work hard; those times when you stay up late and you work hard; those times when don’t feel like working — you’re too tired, you don’t want to push yourself — but you do it anyway. That is actually the dream. That’s the dream. It’s not the destination, it’s the journey. And if you guys can understand that, what you’ll see happen is that you won’t accomplish your dreams, your dreams won’t come true, something greater will. mamba out
那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~
2020.2.26
luogu P1141 01迷宫
整体思想是:记忆化 + dfs
记忆化: 将搜索过程中某一块的内容直接记录下来并且标记该位置已经来过
然后直接将整个一块中所有的内容记录下来赋值到各个块内的每个
位置相连接的联通数量已经访问的就不需要再记录
dfs 遍历方式
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int N = 1010;
int ne[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
int n , m , map[N][N] ,now;bool vis[N][N];
int f[N][N],ans[1000005][2], cnt = 0;
// ans 用来记录所走过的某一块
bool inmap(int x,int y)
{
if(x >= 1 && x <= n && y >= 1 && y <= n)return true;
else return false;
}
void dfs(int x,int y)
{
now++;
ans[now][0] = x;
ans[now][1] = y;
// 利用 now 来记录该区域内走过的连通块
for(int i = 0;i < 4 ;i ++)
{
int nx = x + ne[i][0];
int ny = y + ne[i][1];
if(inmap(nx,ny) && !vis[nx][ny] && map[x][y] != map[nx][ny])
{
vis[nx][ny] = true; // 标记这个块已经被访问过 不用再取消标记
dfs(nx,ny);
}
}
return;
}
void init()
{
cin >> n >> m;
string line;
for(int i = 1;i <= n ;i ++)
{
cin >> line;
for(int j = 0;j < line.size() ;j ++)
{
map[i][j + 1] = (line[j] == '1') ? 1 : 0;
}
}
for(int i = 1;i <= n ;i ++)
{
for(int j = 1;j <= n ;j ++)
{
if(!vis[i][j])
{
vis[i][j] = true;now = 0;
dfs(i,j);
// 直接将ans中记录的某一连通块都初始化为块内的大小
for(int i = 1;i <= now;i ++)f[ans[i][0]][ans[i][1]] = now;
}
}
}
}
int main()
{
init();
int x, y;
for(int i = 0;i < m ;i ++)
{
scanf("%d %d",&x, &y);
printf("%d
",f[x][y]);
}
return 0;
}
bfs版本
bfs + 记忆化
#include <iostream>
#include <algorithm>
#include <string>
#include <queue>
#include <cstdio>
using namespace std;
const int N = 1010;
int n , m , ne[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
int map[N][N] , f[N][N] ,now , ans[1000005][2];
bool vis[N][N];
struct node{
int x , y;
};
bool inmap(int x,int y)
{
if(x >= 1 && x <= n && y >= 1 && y <= n)return true;
else return false;
}
// 通过一遍bfs把答案记录下来
void bfs(int x,int y)
{
now++;ans[now][0] = x;ans[now][1] = y;
queue<node> q;
q.push({x,y});
while(!q.empty())
{
node t = q.front();
for(int i = 0;i < 4;i ++)
{
int nx = t.x + ne[i][0];
int ny = t.y + ne[i][1];
if(inmap(nx,ny) && !vis[nx][ny] && map[t.x][t.y] != map[nx][ny])
{
now++;
ans[now][0] = nx;ans[now][1] = ny;
vis[nx][ny] = true;
q.push({nx,ny});
}
}
q.pop();
}
}
void init()
{
cin >> n >> m;
string line;
for(int i = 1;i <= n ;i ++)
{
cin >> line;
for(int j = 0;j < line.size(); j++)
{
map[i][j + 1] = (line[j] == '1') ? '1' : '0';
}
}
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= n ;j++)
{
if(!vis[i][j])
{
now = 0;vis[i][j] = 1;bfs(i,j);
for(int k = 1;k <= now; k++)f[ans[k][0]][ans[k][1]] = now;
}
}
}
}
int main()
{
init();
for(int i = 0;i < m ;i ++)
{
int x , y ;
scanf("%d %d",&x,&y);
printf("%d
",f[x][y]);
}
return 0;
}
luogu-P1002 过河卒
简单动态规划 需要处理以下特殊坐标
排除码可以跳过的坐标 再将所有的坐标++
因为我们默认从 x = 1 y = 1 开始
/*
简单动态规划 需要处理以下特殊坐标
排除码可以跳过的坐标 再将所有的坐标++
因为我们默认从 x = 1 y = 1 开始
*/
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 22;
int mx , my , tx, ty;
int dir[8][2] = {{1,2},{2,1},{-1,2},{2,-1}
,{-1,-2},{-2,-1},{1,-2},{-2,1}};
long long f[N][N];
bool vis[N][N];
bool inmap(int x,int y)
{
if(x >=1 && x <= N && y >= 1 && y <= N)return 1;
else return 0;
}
void wipe()
{
vis[mx][my] = 1;
for(int i = 0;i < 8; i++)
{
int nx = mx + dir[i][0];
int ny = my + dir[i][1];
if(inmap(nx,ny))vis[nx][ny] = true;
}
}
int main()
{
cin >> tx >> ty >> mx >> my;
tx++;ty++; mx++; my ++;
wipe();
f[1][1] = 1;
for(int i = 1;i <= tx; i++)
{
for(int j = 1;j <= ty ;j ++)
{
if(!vis[i][j]){
f[i][j] += f[i-1][j] + f[i][j-1];
}
}
}
cout << f[tx][ty] << endl;
return 0;
}