越来越不想写博客了。。。。但适当总结是很必要的。
1.深搜和广搜当有多组样例时,注意全局变量的清0和更新,还有数组和标记数组都要清0!!
2.数组标记用了不会错,不用可能超时,尽量都用。
3.一种通过递归记录路径的方法真实太妙了!!虽然我用的广搜的模板,但这个记录路径的方法有深搜的影子,很妙。
https://www.luogu.com.cn/problem/P6207
#include
using namespace std;
struct node
{
int x,y,s;
};
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int r,c,vis[200][200],dist[200][200][2],k;
char a[200][200];
queue<node>q;
void bfs()
{
vis[1][1]=1;
node cur,nxt;
cur.x=1;cur.y=1;cur.s=0;
q.push(cur);
while(!q.empty())
{
cur=q.front();q.pop();
if(cur.x==r&&cur.y==c)
return ;
for(int i=0;i<4;i++)
{
nxt.x=cur.x+dx[i];
nxt.y=cur.y+dy[i];
if(a[nxt.x][nxt.y]=='.'&&vis[nxt.x][nxt.y]==0&&nxt.x>=1&&nxt.x<=r&&nxt.y>=1&&nxt.y<=c)
{
nxt.s=cur.s+1;vis[nxt.x][nxt.y]=1;q.push(nxt);
dist[nxt.x][nxt.y][0]=cur.x;
dist[nxt.x][nxt.y][1]=cur.y;
}
}
}
}
void print(int x,int y)
{
if(!(dist[x][y][0]+dist[x][y][1])) return;
print(dist[x][y][0],dist[x][y][1]);
printf("%d %d\n",x,y);
}
int main()
{
scanf("%d%d",&r,&c);
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
cin>>a[i][j];
bfs();
puts("1 1");
print(r,c);
return 0;
}
4.用while构造不同进制,统计不同进制下的波浪数,卡了我好久,就是想不明白,虽然用到的思想知识构造,捎带一点进位转换。。。
https://www.luogu.com.cn/problem/P1112
#include
using namespace std;
int a,b,c,d,k,f[50],q[10000005],sum,t;
void go(int x)
{
for(int i=1;i<x;i++)
{
for(int j=0;j<x;j++)
{
if(i!=j)
{
sum=0;t=0;
while(sum<=d)
{
if(t%2==0)
{
sum=sum*x+i;t++;
}
else
{
sum=sum*x+j;t++;
}
if(sum>=c&&sum<=d)
q[sum]++;
}
}
}
}
}
int main()
{
cin>>a>>b>>c>>d>>k;
for(int i=a;i<=b;i++)
go(i);
for(int i=c;i<=d;i++)
{
if(q[i]==k)
cout<<i<<endl;
}
return 0;
}
5.next_permutation 函数的使用,列出全排列,基本代码格式:
int main() {
string str; //字符串的全排列
cin>>str;
sort(str.begin(),str.end());
do{
cout<<str<<endl;
}while(next_permutation(str.begin(),str.end()));
return 0;
}
6.杨辉三角的参数计算,这种深搜到的方式掌握的并不好
https://www.luogu.com.cn/problem/P1118
#include
using namespace std;
int pc[50],n;
int main()
{
cin>>n; //输入n,算的是C(0到n-1,n-1)的排列
pc[0]=pc[n-1]=1;
if (n>1)
for (int i=1;i*2<n;i++)
pc[i]=pc[n-1-i]=(n-i)*pc[i-1]/i;//杨辉三角的对称性
for(int i=0;i<n;i++)
cout<<pc[i]<<" ";
cout<<endl;
return 0;
}
#include
using namespace std;
int pc[50],n,k,vis[50],ans[50],sum;
int dfs(int i,int num,int sum) //枚举第i个数,第i个数是什么,当前和sum
{
if(sum>k) return 0;
if(i==n)
{
if(sum==k)
{
ans[i]=num;return 1;
}
else return 0;
}
vis[num]=1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dfs(i+1,j,sum+pc[i]*j))
{
ans[i]=num;return 1;
}
}
vis[num]=0;
return 0;
}
int main()
{
cin>>n>>k; //输入n,算的是C(0到n-1,n-1)的排列
pc[0]=pc[n-1]=1;
if (n>1)
for (int i=1;i*2<n;i++)
pc[i]=pc[n-1-i]=(n-i)*pc[i-1]/i;//杨辉三角的对称性
if(dfs(0,0,0))
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
cout<<endl;
return 0;
}
7.学到一种新的找最长回文字符串的方式。遍历每个字符,通过长度的奇偶比较返回大的那个值。本题从格式处理上增加了难度。
#include
using namespace std;
const int maxn=20005;
char s[maxn],s1[maxn];
int pos[maxn],n,l,t,mn1,ls;
int check(int x)
{
int a1=1,a2=0;
for(int i=x,j=1;i-j>=0&&i+j<l&&s1[i-j]==s1[i+j];j++) //奇数从1开始
a1+=2;
for(int i=x,j=0;i-j>=0&&i+j+1<l&&s1[i-j]==s1[i+j+1];j++) //偶数从0开始
a2+=2;
return max(a1,a2);
}
int main()
{
while((s[n]=getchar())!=EOF) n++;
for(int i=0;i<n;i++)
{
if(isalpha(s[i]))
{
s1[l]=tolower(s[i]);
pos[l++]=i; //提取的字符所在位置
}
}
for(int i=0;i<l;i++)
{
t=check(i);
if(t>mn1)
{
mn1=t;
ls=i+(t/2);
}
}
s[pos[ls]+1]='\0';
printf("%d\n%s\n",mn1,&s[pos[ls-mn1+1]]);
return 0;
}
8.并查集的题目,算作复习一下,用结构体存一直通不过,改为数组存数据就通过了。
啊啊啊啊啊,是我的代码出问题了,有时因为一个下标写错检查半天,我还怀疑是结构体的存储方式出问题了。。。。。我想一头撞死
https://www.luogu.com.cn/problem/P3144
#include
using namespace std;
struct node
{
int l,r;
}e[3005];
int f[3005],n,m,ans,p[3005],q[3005];
int r_find(int r)
{
while(r!=f[r]) r=f[r];
return r;
}
void init()
{
for(int i=1;i<=n;i++)
f[i]=i;
return;
}
void mg(int x,int y)
{
int fx,fy;
fx=r_find(x);fy=r_find(y);
if(fx!=fy)
f[fx]=fy;
}
int check()
{
int k=0;
for(int i=1;i<=n;i++)
{
if(q[i]==1) continue;
if(f[i]==i) k++;
}
if(k>=2) return 0;
else
return 1;
}
int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&e[i].l,&e[i].r);
mg(e[i].l,e[i].r);
}
int k=0;
for(int i=1;i<=n;i++)
{
if(f[i]==i)
k++;
}
if(k>=2)
ans=1;
for(int i=1;i<=n;i++)
{
if(ans==1&&i==1)
{
printf("NO\n");
continue;
}
init();
scanf("%d",&p[i]);
q[p[i-1]]=1; //此农场已关闭
for(int j=1;j<=m;j++)
{
if(q[e[j].l]==0&&q[e[j].r]==0)
mg(e[j].l,e[j].r);
}
if(check())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
9.本题是最长路径,相对于一点到一点的最短路径,优先广度搜索,是一道裸题。
https://www.luogu.com.cn/problem/P1807
#include
using namespace std;
int n,m,edge[5000][5000],f[2000],x,y,z,sum,ans;
queue<int>q;
void bfs()
{
memset(f,-1,sizeof(f));
f[1]=0; //f[i]记录到结点i的最长路
q.push(1); //存放到的点
while(!q.empty())
{
int cur=q.front();
q.pop();
for(int i=1;i<=n;i++)
{
if(edge[cur][i]>0&&f[i]<f[cur]+edge[cur][i])
{
f[i]=f[cur]+edge[cur][i]; //使用max函数反而会超时,因为程序多次进入if语句,被压入队列中
q.push(i);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
edge[x][y]=max(edge[x][y],z);
}
bfs();
cout<<f[n]<<endl;
return 0;
}
10.一个动态迷宫问题。会不断有路障掉下来,本题是输出yes或no,还有一种思路是只考虑路障。
https://www.luogu.com.cn/problem/P3395
#include
using namespace std;
struct node
{
int x,y,t;
};
int mp[1005][1005],zx[2005],zy[2005],fg,n,ans;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
bool vis[1005][1005];
queue<node>q;
void bfs(int x,int y,int t)
{
node cur,nxt;
cur.x=x;cur.y=y;cur.t=t;
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
int a,b,c;a=cur.x;b=cur.y;c=cur.t;
if(a==n&&b==n)
{
fg=1;break;
}
mp[zx[c]][zy[c]]=1;
for(int i=0;i<4;i++)
{
int xx=a+dx[i];int yy=b+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&vis[xx][yy]==0&&mp[xx][yy]==0)
{
nxt.x=xx;nxt.y=yy;nxt.t=c+1;
vis[xx][yy]=1;
q.push(nxt);
}
}
}
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
memset(vis,0,sizeof(vis));
memset(mp,0,sizeof(mp));
fg=0;
scanf("%d",&n);
for(int i=1;i<=2*n-2;i++)
scanf("%d%d",&zx[i],&zy[i]);
vis[1][1]=1;
bfs(1,1,0);
if(fg)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}