几个例题
1.最小转弯问题
题意:从起点出发到终点所需的最小转弯数
其实就是一行一行地bfs,有几个小细节。
主要还是bfs用队列实现的问题
void bfs(int x,int y){
//其实就是添加队首操作,记得初始化step
now.x=x;
now.y=y;
now.step=0;
q.push(now);
while(!q.empty()){
node next;
//为啥oj不认我的二维方向数组呢??
for(int k=0;k<4;k++){
no = q.front();
next.x =no.x+nextx[k];
next.y=no.y+nexty[k];
while(next.x>0&&next.x<=n&&next.y>0&&next.y<=m
&&!map[next.x][next.y])
{
//注意点一:因为是一行一行直接bfs的,有可能会走过头so我们修改都时候要带上vis过的点哦
//不然就没法回头了,所以vis要拿出来单独判断
if(!vis[next.x][next.y]){
if(next.x==tx&&next.y==ty){
//注意点二:这里的step是上一个的 因为本次不需要转弯就到达了终点
cout<<no.step<<endl;
return;
}
vis[next.x][next.y]=1;
next.step =no.step+1;
q.push(next);
}
next.x+=nextx[k];
next.y+=nexty[k];
}
}
//注意位置ang
q.pop();
}
return ;
}
2.数独数独
九个小格子判断那里有点意思,像映射思想,
其实是构造了二元分段函数来的,分别对应那9个小格子
#include<iostream>
using namespace std;
int m[10][10];
bool visc[10][10],visr[10][10],visg[10][10];
//vis 是 1-9 列/行/小方格 中 1-9 是否出现过
void print(){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
cout << m[i][j]<<" ";
}
cout << endl;}
}
void dfs(int x,int y){//x行y列
if(m[x][y]!=0){
if(x==9&&y==9) {
print();
} //x行9列已搜完 搜x+1行
else if(y==9) dfs(x+1,1);
else dfs(x,y+1); }
if(m[x][y]==0){
for(int i=1;i<=9;i++){
if(!visr[x][i]&& !visc[y][i]&&
!visg[(x-1)/3*3+(y-1)/3+1][i]){
m[x][y]=i;
visr[x][i]=1;
visc[y][i]=1;
visg[(x-1)/3*3+(y-1)/3+1][i]=1;
if(x==9&&y==9){
print(); }
else if(y==9) dfs(x+1,1);
else dfs(x,y+1);
m[x][y]=0;
visr[x][i]=0;
visc[y][i]=0;
visg[(x-1)/3*3+(y-1)/3+1][i]=0; } } }}
int main(){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++) {
cin>>m[i][j];
if(m[i][j]>0){
visr[i][m[i][j]]=1;
visc[j][m[i][j]]=1;
visg[(i-1)/3*3+(j-1)/3+1][m[i][j]]=1; } } }
dfs(1,1);}
2.单词方阵
题意 在一个字符方阵里找到给定字符串并高亮显示
dfs快乐 记得每一次要搜八个方向 中途不可换方向哦 一开始没发现自己错在哪里
要开一个结构存储目前路径啊
//x,y目前位置 id是字符序号 当前正要匹配哪一个,d 是方向有8个,要枚举
void dfs(int x,int y,int id,int d){
if(x<1||x>n||y<1||y>n) return;
if(id>6){
for(int i=0;i<=6;i++){
// cout<<temp[6].x<<" "<<temp[6].y<<endl;
book[temp[i].x][temp[i].y]=1;
// if(book[1][7])cout<<book[1][7]<<endl;
}
return;
}
else{
int tx=x+next[d][0];
int ty=y+next[d][1];
// if(tx<0||tx>n||ty<0||ty>n) return;
if(map[tx][ty]==t[id]){
temp[id].x=tx;
temp[id].y=ty;
dfs(tx,ty,id+1,d);
}}
return ;
}
3.洛谷p1441
有多种实现
先上一个超时的bfs吧。
#include<iostream>
#include<cmath>
#include<string.h>
#include<iomanip>
#include<queue>
using namespace std;
struct p{
int x;int y;
};
//bfs当然是要用队列的
queue <p>xx ;
int n,m,sx,sy;
int next[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int a[10005][10005];
bool vis[10005][10005];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
string x;cin>>x;
for(int j=1;j<=n;j++){
a[i][j]=x[j-1]-'0';
}
}
p t;
for(int i=1;i<=m;i++){
int ans=1;
while(!xx.empty())xx.pop();
memset(vis,0,sizeof(vis));
cin>>t.x>>t.y;
xx.push(t);
vis[t.x][t.y]=1;
while(!xx.empty()){
//如果放在最后就不对啦,因为最后一个点还没统计就pop了,这时候已经空了,跳出循环
//所以会错掉
//注意这个pop位置很玄妙,没有测试数据我根本调不出来= =。
xx.pop();
for(int k=0;k<4;k++){
p g;
g.x=t.x+next[k][0];
g.y=t.y+next[k][1];
if(g.x>=1&&g.x<=n&&
g.y>=1&&g.y<=n&&!vis[g.x][g.y]){
if(a[g.x][g.y]!=a[t.x][t.y]){
vis[g.x][g.y]=1;
xx.push(g);
ans++;
}
else continue;
}
}
t = xx.front();
}
cout<<ans<<endl;
}
}
emm然后是统计联通块的bfs不超时了
#include<iostream>
#include<cmath>
#include<string.h>
#include<iomanip>
#include<queue>
using namespace std;
struct p{
int x;int y;
};
queue <p>xx ;
int n,m,sx,sy;
int next[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int a[10005][10005];
//把vis改成int用来记录联通块的序号
int vis[10005][10005];
//ans预处理存储答案,询问时直接输出
int ans[100000005];
int main(){
int d=0;
cin>>n>>m;
for(int i=1;i<=n;i++){
string x;cin>>x;
for(int j=1;j<=n;j++){
a[i][j]=x[j-1]-'0';
}
}
//预处理一般是每个点都遍历一下的,这样才能加快速度啊
//多组数据要记得初始化。
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!vis[i][j]){
d++;
p t;
t.x=i;t.y=j;
//vis[t.x][t.y]=1;
xx.push(t);
int sum=0;
while(!xx.empty()){
p g;
for(int k=0;k<4;k++){
g.x=t.x+next[k][0];
g.y=t.y+next[k][1];
//注意还是要判断重复,不然会死循环
if(!vis[g.x][g.y]&&
g.x>=1&&g.x<=n&&
g.y>=1&&g.y<=n){
if(a[g.x][g.y]!=a[t.x][t.y]){
sum++;
vis[g.x][g.y]=d;
xx.push(g);
}
}
}
xx.pop();
t=xx.front();
}
//每个联通块里面每个点的答案是一样的
ans[d]=sum;
}
}
}
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
if(ans[vis[x][y]])
cout<<ans[vis[x][y]]<<endl;
//如果那个地方找不到的话,因为我bfs写得太垃圾的原因是走不到1的,所以我们手动调整一下。。
else cout<<1<<endl;
}
}
4.这几天又做了一个妙绝的数独。
洛谷p1074靶型数组,是数独的更快解法,之前那个虽然工整,但是慢。
要求先搜已知项最多的行与列,可以减少尝试,这样之前数独就不行了,因为那个是一行一行按顺序搜,所以跳出条件改成统计有效数字个数=81,每次选取下一个都优化一下,具体实现看码
真的神仙啊!还有舞蹈链做法(自带剪枝的神秘数据结构),不过还没打算研究。
#include<iostream>
#include<cmath>
#include<string.h>
#include<stdio.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int map[10][10];
int vx[10][10];
int vy[10][10];
int vg[10][10];
int ans=-1;
int t[10][10];
int c_x[10],c_y[10];
//算加权的
int cal(){
int sum=0;
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
if(i==1||i==9||j==1||j==9){
sum+=6*t[i][j];
}
else if(i==2||i==8||j==2||j==8){
sum+=7*t[i][j];
}
else if(i==3||i==7||j==3||j==7){
sum+=8*t[i][j];
}
else if(i==4||i==6||j==4||j==6){
sum+=9*t[i][j];
}
else if(i==5&&j==5) sum+=10*t[i][j];
}
}
return sum;
}
//啊!
void dfs(int x,int y,int cnt){
if(cnt==81){
ans = max(ans,cal());
return;
}
else
for(int i=1;i<=9;i++){
if(!vx[x][i]&&!vy[y][i]&&!vg[3*((x-1)/3)+(y-1)/3+1][i]){
t[x][y]=i;
vx[x][i]=1;
vy[y][i]=1;
vg[3*((x-1)/3)+(y-1)/3+1][i]=1;
//这两个就是记录每行非0的个数了
c_x[x]++; c_y[y]++;
int nx=0,ny=0,mx=-1,my=-1;
for(int j=1;j<=9;j++){
if(c_x[j]>mx&&c_x[j]<9)
mx=c_x[j],nx=j;
}
//先把nx确定下来,再在nx行找ny
for(int j=1;j<=9;j++){
if(c_y[j]>my&&!t[nx][j])
my=c_y[j],ny=j;
}
dfs(nx,ny,cnt+1);
t[x][y]=0;
vx[x][i]=0;
vy[y][i]=0;
vg[3*((x-1)/3)+(y-1)/3+1][i]=0;
c_x[x]--;
c_y[y]--;
}
}
}
int cnt=0;
int main(){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
cin>>map[i][j];
if(map[i][j]>0) {
cnt++;//记得加初始已知项啊 不然无解。
t[i][j]=map[i][j];
vx[i][map[i][j]]=1;
vy[j][map[i][j]]=1;
c_x[i]++;c_y[j]++;
vg[3*((i-1)/3)+(j-1)/3+1][map[i][j]]=1;
}
}
}
//重复一遍,其实写个函数更好看写i
int nx,ny,mx=-1,my=-1;
for(int i=1;i<=9;i++){
if(c_x[i]>mx&&c_x[i]<9)
mx=c_x[i],nx=i;
}
for(int i=1;i<=9;i++){
if(c_y[i]>my&&!t[nx][i])
my=c_y[i],ny=i;
}
//print();
dfs(nx,ny,cnt);
cout <<ans<<endl;
}
5.洛谷幻想迷宫
一个有点小要求的dfs
为了判断是不是走过,新开了数组记录取模前的原始数据
#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,sx,sy;
bool ans=0;
char mp[2000][2000];
int book[2000][2000][3];
bool vis[2000][2000];
int nxt[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void dfs(int x,int y,int lx,int ly){
if(ans) return ;
if(vis[x][y]&&(book[x][y][1]!=lx||book[x][y][2]!=ly)){
ans =1;
return;
}
book[x][y][1]=lx;
book[x][y][2]=ly;
vis[x][y]=1;
for(int k=0;k<4;k++){
int nx=x+nxt[k][0];
int ny=y+nxt[k][1];
if(nx==0) nx=n;
if(nx==n+1) nx=1;
if(ny==0) ny=m;
if(ny==m+1) ny=1;
//这里的lxx记得要新建,不可在lx上改动啊 不然出了循环就gg
int lxx = lx+nxt[k][0];
int lyy = ly+nxt[k][1];
if(mp[nx][ny]=='.'||mp[nx][ny]=='S'){
if(book[nx][ny][1]!=lxx||book[nx][ny][2]!=lyy||!vis[nx][ny]){
dfs(nx,ny,lxx,lyy);
}
}
}
}
int main(){
while(cin>>n>>m){
ans =0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
mp[i][j]='0';
book[i][j][1]=0;
book[i][j][2]=0;
vis[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>mp[i][j];
if(mp[i][j]=='S'){
sx=i;sy=j;
}
}
}
dfs(sx,sy,sx,sy);
if(ans) cout<<"Yes"<<endl;
else cout << "No"<<endl;
}
return 0;
}
6.P1363 创意吃鱼法
(1)给个我的辣鸡超时版 暴力dfs 剪枝无能QwQ
#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,ans,maxnn;
int mp[3000][3000];
bool dfs(int x,int y,int k){
if(k==1){
if(mp[x][y]) {
ans = max(ans,1);
return 1;
}
else return 0;
}
if(ans>=k) return 0;
bool f1=1,f2=1;
for(int i=x;i<=x+k-1;i++){
if(!f1) break;
for(int j=y;j<=y+k-1;j++){
if(i-x==j-y){
if(!mp[i][j]){
f1=0;
break;
}
}
else {
if(mp[i][j]){
f1=0;
break;
}
}
}
}
for(int i=x;i<=x+k-1;i++){
if(!f2) break;
for(int j=y;j<=y+k-1;j++){
if(i-x+j-y==k-1){
if(mp[i][j]==0){
f2=0;
break;
}
}
else{
if(mp[i][j]==1){
f2=0;
break;
}
}
}
}
if(f1||f2){
ans = max(ans,k);
return 1;
}
else return 0;
}
int main(){
cin >> n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin >> mp[i][j];
}
}
for(int i=1;i<=n;i++){
if(ans>=n-i+1)break;
for(int j=1;j<=m;j++){
if(ans>=m-j+1) break;
for(int k=min(n-i+1,m-j+1);k>=1;k--){
if(k<ans) break;
if(dfs(i,j,k)){
//cout << i <<" "<<j<<" "<<k<<endl;
break;
}
}
}
}
cout << ans <<endl;
return 0;
}
(2)正解 我觉得妙(前缀预处理加速 分两种情况判断:对角线和右对角线)
#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,ans;
int mp[3000][3000];
int s[3000][3000];
void workl(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int k=0;
while(1){
k++;
//(i,j)是左上顶点 对角线向右向下
if(k+i-1>n||k+j-1>m) break;
if(s[i+k-1][j+k-1]-s[i+k-1][j-1]-s[i-1][j+k-1]+s[i-1][j-1]==k){
if(mp[i][j]&&mp[i+k-1][j+k-1]) ans = max(ans,k);
else break;
}
else break;
}
}
}
}
void workr(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int k=0;
while(1){
k++;
//(i,j)是右上顶点 对角线向左向下
if(k+i-1>n||j-k+1<=0) break;
if(s[i+k-1][j]-s[i+k-1][j-k]-s[i-1][j]+s[i-1][j-k]==k){
if(mp[i][j]&&mp[i+k-1][j-k+1]) ans=max(ans,k);
else break;
}
else break;
}
}
}
}
int main(){
cin >> n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin >> mp[i][j];
}
}
//处理前缀和
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+mp[i][j];
}
}
workl();
workr();
cout << ans <<endl;
return 0;
}
(3)dp版
#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,ans;
const int inf=0x3f3f3f3f;
int mp[3000][3000];
int dp[3000][3000];
void up(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ans = max(ans,dp[i][j]);
}
}
}
void ini(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=mp[i][j];
}
}
}
void workl(){
ini();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]&&dp[i-1][j-1]){
bool f=1;int l=inf;
for(int k=i-1;k>=i-dp[i-1][j-1]&&f;k--){
if(mp[k][j]) f=0,l=min(l,i-k);
}
for(int k=j-1;k>=j-dp[i-1][j-1]&&f;k--){
if(mp[i][k]) f=0,l=min(l,j-k);
}
if(f) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=l;
}
}
}
up();
}
void workr(){
ini();
for(int i=1;i<=n;i++){
for(int j=m;j>=1;j--){
if(mp[i][j]&&dp[i-1][j+1]){
bool f=1;int l=inf;
for(int k=j+1;k<=j+dp[i-1][j+1]&&f;k++){
if(mp[i][k]) f=0,l=min(l,k-j);
}
for(int k=i-1;k>=i-dp[i-1][j+1]&&f;k--){
if(mp[k][j]) f=0,l=min(l,i-k);
}
if(f) dp[i][j]=dp[i-1][j+1]+1;
else dp[i][j]=l;
}
}
}
up();
}
int main(){
cin >> n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin >> mp[i][j];
}
}
workl();
workr();
cout << ans <<endl;
return 0;
}
7.中规中矩的dfs 洛谷P1120
很巧妙的剪枝和预处理
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cmath>
#include<algorithm>
using namespace std;
int n,cnt,sum,a[70],num,per,nxt[70];
bool f=0,vis[70];
//k是当前木棍数,last上一个木棍方便撤回,res当前木棍剩余量
void dfs(int k,int last,int res){
if(f) return;
if(res==0){
if(k==num){
f=1;
return ;
}
int t;
for(int i=1;i<=cnt;i++){
if(!vis[i]){
t=i;
break;
}
}
vis[t]=1;
dfs(k+1,t,per-a[t]);
vis[t]=0;
if(f) return ;
}
//找出第一个长度<=res的位置
int l=last+1,r=cnt;
int mid;
while(l<r){
mid=(l+r)>>1;
if(a[mid]<=res) r=mid;
else l=mid+1;
}
for(int i=l;i<=cnt;i++){
if(!vis[i]){
vis[i]=1;
dfs(k,i,res-a[i]);
vis[i]=0;
if(f) return ;
//如果剩下的拼不出想要的长度,
if(res==a[i]||a[i]==per) return;
i=nxt[i];
if(i==cnt) return;
}
}
}
bool cmp(int x,int y){
return x>y;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
//题目条件看错了,我......
if(x<=50) {
a[++cnt]=x;
sum+=x;
}
}
//预处理 按倒序排列 这样先拼大的再用小的拼出大的,总是有解的
//但是如果乱序,先拼小的,后面大的是没用的
sort(a+1,a+1+cnt,cmp);
//nxt预处理,如果dfs时候一根木棍不行那么后面与它长度相等的也不行
nxt[cnt]=cnt;
for(int i=cnt-1;i>0;i--){
if(a[i]==a[i+1]) nxt[i]=nxt[i+1];
else nxt[i]=i;
}
//开始枚举 (maxn,sum)
for(int i=a[1];i<=sum/2;i++){
if(sum%i==0){
f=0;
per=i;
num=sum/per;
vis[1]=1;
dfs(1,1,per-a[1]);
vis[1]=0;
if(f){
cout<<per<<endl;
return 0;
}
}
}
cout<<sum<<endl;
return 0;
}
- dfs 水 P2404
我已经无聊到做这种题来消磨时间了吗
#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int maxn = 1e3 + 5;
int n;
int book[10];
void work(int last,int cur, int target,string s) {
if (cur > target) return;
if (cur == target && last != target) {
cout <<s<< endl;
return;
}
for (int i = last;i <= target - cur;i++) {
string tmp = s;
s += char('0' + i);
if(cur+i != target) s += '+';
work(i,cur + i, target,s);
s = tmp;
}
}
int main(){
cin >> n;
work(1,0, n, "");
return 0;
}
P1433
TSP问题鸭,竟然没想出来,其实容易被思维定势
正解是状压dp,dfs挂了最后一个点
(1)DFS(WA的
#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int maxn = 1e3 + 5;
int n;
double ans = INF;
bool vis[maxn];
struct P {
double x, y;
}p[maxn];
double dis(P p1, P p2) {
double res = 0;
res = sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
return res;
}
bool check() {
for(int i = 1;i <= n;i++) {
if (!vis[i]) return false;
}
return true;
}
void dfs(int id,double tot) {
if (tot >= ans) return;
if (check()) {
ans = min(ans, tot);
return;
}
for (int i = 1;i <= n;i++) {
if (!vis[i]) {
vis[i] = 1;
dfs(i, tot + dis(p[id], p[i]));
vis[i] = 0;
}
}
return;
}
int main(){
cin >> n;
p[0].x = p[0].y = 0;
for (int i = 1;i <= n;i++) {
cin >> p[i].x >> p[i].y;
}
dfs(0,0);
cout << fixed << setprecision(2)<<ans << endl;
return 0;
}
(2)状压DP
要记得初始化和处理边界条件
#include <iostream>
#include <string>
#include<cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int maxn = 1e3 + 5;
const int N = 20;
int n;
double ans = INF;
bool vis[maxn];
double dp[20][1 << 20];
struct P {
double x, y;
}p[maxn];
double dis(P p1, P p2) {
double res = 0;
res = sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
return res;
}
bool check() {
for (int i = 1;i <= n;i++) {
if (!vis[i]) return false;
}
return true;
}
void dfs(int id, double tot) {
if (tot >= ans) return;
if (check()) {
ans = min(ans, tot);
return;
}
for (int i = 1;i <= n;i++) {
if (!vis[i]) {
vis[i] = 1;
dfs(i, tot + dis(p[id], p[i]));
vis[i] = 0;
}
}
return;
}
int main() {
//cout << (1 << 20) << endl;
cin >> n;
p[0].x = p[0].y = 0;
for (int i = 1;i <= n;i++) {
cin >> p[i].x >> p[i].y;
}
for (int i = 1;i <= (1 << n);i++) {
for (int j = 1;j <= n;j++) {
dp[j][i] = INF;
}
}
for (int s = 1;s <=(1 << n)-1;s++) {
for (int i = 1;i <= n;i++) {
//如果没有挑选第i个,跳过
if ((s&(1 << (i - 1))) == 0)continue;
//以i为开头,后面还暂时没有(边界)
if (s == (1 << (i - 1))) { dp[i][s] = 0;continue; }
for (int j = 1;j <= n;j++) {
if (!((s&(1 << (j - 1))) == 0 || i == j)) {
dp[i][s] = min(dp[i][s], dp[j][s - (1 << (i - 1))] + dis(p[i], p[j]));
}
}
}
}
for (int i = 1;i <= n;i++) {
ans = min(ans, dp[i][(1 << n) - 1] + dis(p[0], p[i]));
}
cout << fixed << setprecision(2) << ans << endl;
return 0;
}
P1825
BFS,没看出坑在哪里,但是我写挂了
#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int maxn = 1e3 + 5;
int n, m,sx,sy,ex,ey,ans;
struct P {
int x, y,t;
P(int xx, int yy,int tt) {
x = xx;y = yy;t = tt;
};
P(){};
};
struct Door {
P p1, p2;
int cnt;
}door[maxn];
int nxt[4][2] = { {0,1},{0,-1},{1,0},{-1,0}};
char mp[505][505];
bool vis[505][505];
P fuk(P t) {
P res;
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
if (mp[t.x][t.y] == mp[i][j] && (i != t.x || j !=t.y)) {
res.x = i;
res.y = j;
res.t = t.t;
return res;
}
}
}
}
void bfs() {
queue<P> q;
q.push(P(sx, sy, 0));
while (!q.empty()) {
P u = q.front();
q.pop();
if (mp[u.x][u.y] == '=') {
cout << u.t << endl;
return;
}
if (mp[u.x][u.y] >= 'A' && mp[u.x][u.y] <= 'Z') {
u = fuk(u);
}
for (int k = 0;k < 4;k++) {
int nx = u.x + nxt[k][0];
int ny = u.y + nxt[k][1];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m
&& mp[nx][ny] != '#' && !vis[nx][ny]) {
vis[nx][ny] = 1;
q.push(P(nx, ny, u.t + 1));
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
cin >> mp[i][j];
if (mp[i][j] == '@') {
sx = i;sy = j;
}
}
}
bfs();
return 0;
}
P1032 字符串拼接
噢老天爷我为什么要用dfs,bfs不香吗
又wa又t的dfs,我lay了
学习了双向bfs,挺好
//感谢logu 大佬 BrandonSoong
#include"pch.h"
#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int maxn = 1e3 + 5;
string A, B;
int num = 0, begin_pos = 0, end_pos = 0;
struct P {
string u, v;
}p[maxn];
bool flag = 0;
map<string,int> mp;
string replace(string a, string cur) {
string res = "";
for (int i = 0;i < begin_pos;i++)
res += cur[i];
res += a;
for (int i = end_pos + 1;i < cur.length();i++)
res += cur[i];
return res;
}
bool issub(string a, string A) {
// cout << "is "<<a<<" the substring of" << A << endl;
int nxt = begin_pos = end_pos = 0;
for (int i = 0;i < A.length();i++) {
int start = i;
int j = 0;
while (j < a.length()) {
if (A[start + j] != a[j]) break;
j++;
}
if (j == a.length()) {
begin_pos = i;
end_pos = begin_pos + a.length() - 1;
return 1;
}
}
return 0;
}
struct PP {
int t;
string s;
PP(string ss,int tt) {
t = tt;
s = ss;
}
PP() {};
};
//这个bfs,挂了
void bfs() {
queue<PP>q;
mp[A] = 1;
PP cur;cur.s = A;cur.t = 0;
q.push(cur);
while (!q.empty()&&!flag) {
PP uu = q.front();
if (uu.s == B) {
flag = 1;
cout << uu.t << endl;
return;
}
if (uu.t > 10) return;
q.pop();
for (int i = 1;i <= num;i++) {
if (issub(p[i].u, uu.s)) {
string new_cur = replace(p[i].v,uu.s);
if (!mp[new_cur]) {
mp[new_cur] = 1;
PP v;v.s = new_cur;v.t = uu.t + 1;
if (new_cur == B) {
flag = 1;
cout << v.t << endl;
return;
}
else {
q.push(v);
}
}
}
}
}
}
//
queue<string> a, b;
map<string, int> mpa, mpb;
int two_bfs() {
int step = 0;
a.push(A);b.push(B);
mpa[a.front()] = 0; mpb[b.front()] = 0;
//cout << mpa[A] << mpb[B] << endl;
string s, s2;
while (++step <= 5) {
while (mpa[a.front()] == step - 1) {
s = a.front();
a.pop();
for (int i = 1;i <= num;i++) {
unsigned int pos = 0;
while (pos < s.length()) {
if (s.find(p[i].u, pos) == s.npos) {
break;
}
s2 = s;
s2.replace(s2.find(p[i].u, pos), p[i].u.length(), p[i].v);
if (mpa.find(s2) != mpa.end()) {
pos++;
continue;
}
if (mpb.find(s2) != mpb.end()) {
return 2 * step - 1;
}
a.push(s2);
mpa[s2] = step;
pos++;
}
}
}
while (mpb[b.front()] == step - 1) {
s = b.front();
b.pop();
for (int i = 1;i <= num;i++) {
unsigned int pos = 0;
while (pos < s.length()) {
if (s.find(p[i].v, pos) == s.npos) {
break;
}
s2 = s;
s2.replace(s2.find(p[i].v, pos), p[i].v.length(), p[i].u);
if (mpb.find(s2) != mpb.end()) {
pos++;
continue;
}
// cout <<"B: "<< nxts << endl;
if (mpa.find(s2) != mpa.end()) {
return 2 * step;
}
b.push(s2);
mpb[s2] = step;
pos++;
}
}
}
}
return -1;
}
int main() {
cin >> A >> B;
string s1, s2;
while (cin >> s1 >> s2) {
p[++num].u = s1;
p[num].v = s2;
}
int ans = two_bfs();
if (ans != -1) cout <<ans << endl;
else cout << "NO ANSWER!" << endl;
return 0;
}
因为一句位置写错了,debug到半夜,累了睡了睡了