1.带分数
dfs
#include <iostream>
#include <vector>
using namespace std;
long long n,ans;
const int N=10;
bool st[N];
vector<int>num;
int calc(int l,int r){
int sum=0;
for(int i=l;i<r;i++){
sum*=10;
sum+=num[i];
}
return sum;
}
void check(vector<int>num){
for(int i=1;i<=7;i++){
for(int j=i+1;j<=8;j++){
int a=calc(0,i);
//printf("a=%d\n",a);
if(a>n)continue;
int b=calc(i,j);
//printf("b=%d\n",b);
int c=calc(j,9);
//printf("c=%d\n",c);
if(a*c+b==n*c)ans++;
}
}
return;
}
void dfs(int level){
if(level==9){
//puts("!");
//for(int i=0;i<9;i++){
// cout<<num[i];
//}
//puts("!");
check(num);
return;
}
for(int i=1;i<=9;i++){
if(!st[i]){
num.push_back(i);
st[i]=true;
dfs(level+1);
st[i]=false;
num.pop_back();
}
}
}
int main()
{
scanf("%d",&n);
dfs(0);
printf("%lld",ans);
return 0;
}
2.走迷宫
走迷宫
bfs
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int,int>PII;
#define x first
#define y second
const int N=110;
int n,m;
int inx,iny,outx,outy;
int mp[N][N];
int dis[N][N];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
queue<PII>q;
int bfs(int x,int y){
dis[x][y]=0;
q.push({x,y});
while(!q.empty()){
PII t=q.front();
q.pop();
int x=t.x,y=t.y;
for(int i=0;i<4;i++){
int sx=x+dx[i],sy=y+dy[i];
if(mp[sx][sy]&&!dis[sx][sy]&&sx>=0&&sx<n&&sy>=0&&sy<m){
dis[sx][sy]=dis[x][y]+1;
if(sx==outx-1&&sy==outy-1)return dis[sx][sy];
q.push({sx,sy});
}
}
}
return -1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&mp[i][j]);
}
}
scanf("%d%d%d%d",&inx,&iny,&outx,&outy);
printf("%d",bfs(inx-1,iny-1));
return 0;
}
3.蓝桥幼儿园
并查集
#include <iostream>
using namespace std;
const int N=2e5+10;
int p[N];
int find(int x){
if(p[x]!=x)return p[x]=find(p[x]);
return p[x];
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
//初始化
for(int i=1;i<=n;i++){
p[i]=i;
}
for(int i=0;i<m;i++){
int op;
scanf("%d",&op);
int a, b;
scanf("%d%d",&a,&b);
if(op==1){
p[find(a)]=find(b);
}else if(op==2){
bool is=(find(a)==find(b));
if(is){
puts("YES");
}else{
puts("NO");
}
}
}
return 0;
}
4.跳石头
最短最长,最长最短,最大最小,最小最大问题一般用二分搞定。
没有做过类似的题的话思路不太好想
这里是对最短距离进行二分
check函数检查最短距离为mid时去掉石头数量是否小于等于m,查找满足性质的边界值(即去掉石头小于等于m的最大mid值)即为ans
选择的模板是根据更新后r=mid还是r=mid进行判断
#include <iostream>
using namespace std;
const int N=5e4+10;
int stone[N];
int l,n,m;
bool check(int mid){
int now=0;//上一块石头
int sum=0;//移除石头总数
//起点stone[0]=0,默认移走右边的石头
for(int i=1;i<=n;i++){
if(stone[i]-stone[now]<mid){sum++;
//printf("stone%d\n",i);
}
else now=i;
}
// printf("mid=%d\n",mid);
//printf("sum=%d\n",sum);
return sum<=m;
}
int search(int l,int r){
while(l<r){
int mid=l+r+1>>1;
if(check(mid))l=mid;
else r=mid-1;
}
return r;
}
int main()
{
scanf("%d%d%d",&l,&n,&m);
//中间的石头
for(int i=1;i<=n;i++){
scanf("%d",&stone[i]);
}
printf("%d",search(0,l));
return 0;
}