寒假洛谷刷题技巧
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寒假洛谷刷题技巧相关的知识,希望对你有一定的参考价值。
越来越不想写博客了。。。。但适当总结是很必要的。
1.深搜和广搜当有多组样例时,注意全局变量的清0和更新,还有数组和标记数组都要清0!!
2.数组标记用了不会错,不用可能超时,尽量都用。
3.一种通过递归记录路径的方法真实太妙了!!虽然我用的广搜的模板,但这个记录路径的方法有深搜的影子,很妙。
https://www.luogu.com.cn/problem/P6207
#include <bits/stdc++.h>
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 <bits/stdc++.h>
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 <bits/stdc++.h>
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 <bits/stdc++.h>
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 <bits/stdc++.h>
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 <bits/stdc++.h>
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 <bits/stdc++.h>
using namespace std;
int n,m,edge[5000][5000],f[2000],x,y,z,sum,ans;
queue<int>q;
void bfs()
memset(f,以上是关于寒假洛谷刷题技巧的主要内容,如果未能解决你的问题,请参考以下文章