三亚网站怎么制作常用的搜索引擎有哪些?
1、递归+回溯算法
大致思想:从开始若满足条件则一直往后递归下去,直到条件不符或者已完成任务回溯到前一个状态,用来找到所有符合条件的情况。
例题:
题目背景
猪猪 Hanke 得到了一只鸡。
题目描述
猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 10 种配料(芥末、孜然等),每种配料可以放 1 到 3 克,任意烤鸡的美味程度为所有配料质量之和。
现在, Hanke 想要知道,如果给你一个美味程度 n ,请输出这 10 种配料的所有搭配方案。
输入格式
一个正整数 n,表示美味程度。
输出格式
第一行,方案总数。
第二行至结束,10 个数,表示每种配料所放的质量,按字典序排列。
如果没有符合要求的方法,就只要在第一行输出一个 0。
输入输出样例
输入 #1复制
11
输出 #1复制
10 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
说明/提示
对于 100% 的数据,n≤5000。
#include<bits/stdc++.h>
using namespace std;
vector<vector<int>> res; //存储所有组合
void backtrack(int step,int current_sum,vector<int>& path,int n){if(step==10){if(current_sum==n)res.push_back(path); //若十种配料都齐了且总量为n则加入组合,否则返回回溯 return ;}for(int i=1;i<=3;i++){int remaining=10-step-1;int min_required=remaining*1;int max_required=remaining*3;int new_sum=current_sum+i;//当前i无法形成有效组合,剪枝 if(new_sum+min_required>n) continue;if(new_sum+max_required<n) continue;path.push_back(i); //可以加入当前i,到下一种配料 backtrack(step+1,new_sum,path,n);path.pop_back(); //回溯到前一个状态 }
}
int main(){int n;cin>>n;if(n<10||n>30){cout<<0<<endl;return 0;} vector<int> path;backtrack(0,0,path,n);cout<<res.size()<<endl;for(auto& v:res){ //增强for循环,自推导类型auto for(int i=0;i<10;i++){cout<<v[i]<<" ";}cout<<endl;}return 0;
}
2、最大公约数与数字查找
题目描述
将 1,2,…,9 共 9 个数分成三组,分别组成三个三位数,且使这三个三位数的比例是 A:B:C,试求出所有满足条件的三个三位数,若无解,输出 No!!!
。
//感谢黄小U饮品完善题意
输入格式
三个数,A,B,C。
输出格式
若干行,每行 3 个数字。按照每行第一个数字升序排列。
输入输出样例
输入 #1复制
1 2 3
输出 #1复制
192 384 576 219 438 657 273 546 819 327 654 981
说明/提示
保证 A<B<C。
upd 2022.8.3:新增加二组 Hack 数据。
大致思路:首先对输入的比例进行判断,如果有0出现是没有意义的直接输出No,然后将比例化为最简整数比,以便找出所有的组合,这里用到了找最大公约数函数gcd,即循环取余直至为0。然后要生成1~9组成的三个数形成对应比例,即a*k,b*k,c*k三个数。对k的取值进行限定,然后对生成的数进行逐位判断即可,数中不包含0,无重复数字,包含了0~9,这里用到了位掩码,即used |=(1<<d);//表示将第d位数字设置为1;used&(1<<d)//判断第d位是否为1.代码如下:
#include<bits/stdc++.h>
using namespace std;
//求最大公约数,循环取余
int gcd(int a,int b){while(b){int temp=a%b;a=b;b=temp;}return a;
}
//检查数字是1~9
bool check(int x,int y,int z){int used=0; //用位掩码来表示各个位置的状态 int digits[9];digits[0]=x/100; //百位 digits[1]=(x/10)%10; //十位 digits[2]=x%10; //个位 digits[3]=y/100;digits[4]=(y/10)%10;digits[5]=y%10;digits[6]=z/100;digits[7]=(z/10)%10;digits[8]=z%10;//数字不为0且不重复 for(int i=0;i<9;i++){int d=digits[i];if(d==0||used&(1<<d))//检查第d位是否出现过 return false;used |=(1<<d); //将第d位设置为1 }//确保数字包含1~9 return used==0b1111111110;
}
int main(){int A,B,C;cin>>A>>B>>C;if(A==0||B==0||C==0){cout<<"No!!!"<<endl;return 0;} int g=gcd(gcd(A,B),C);int a=A/g,b=B/g,c=C/g;int low=100/a;int high=999/c;vector<vector<int>> result; for(int k=low;k<=high;k++){int x=a*k,y=b*k,z=c*k;if(check(x,y,z))result.push_back({x,y,z});}if(result.empty()){cout<<"No!!!"<<endl;}else{for(const auto &ele:result){cout<<ele[0]<<" "<<ele[1]<<" "<<ele[2]<<endl;}} return 0;
}
3、矩阵旋转
方阵顺时针旋转90度:先把方阵转置,即将对角线两边对称的元素交换位置,然后再将每一行反转reverse,逆时针则先反转每一行再将对角线两边对称的元素交换位置。
例题:
题目描述
Scarlet 最近学会了一个数组魔法,她会在 n×n 二维数组上将一个奇数阶方阵按照顺时针或者逆时针旋转 90∘。
首先,Scarlet 会把 1 到 n2 的正整数按照从左往右,从上至下的顺序填入初始的二维数组中,然后她会施放一些简易的魔法。
Scarlet 既不会什么分块特技,也不会什么 Splay 套 Splay,她现在提供给你她的魔法执行顺序,想让你来告诉她魔法按次执行完毕后的二维数组。
输入格式
第一行两个整数 n,m,表示方阵大小和魔法施放次数。
接下来 m 行,每行 4 个整数 x,y,r,z,表示在这次魔法中,Scarlet 会把以第 x 行第 y 列为中心的 2r+1 阶矩阵按照某种时针方向旋转,其中 z=0 表示顺时针,z=1 表示逆时针。
输出格式
输出 n 行,每行 n 个用空格隔开的数,表示最终所得的矩阵
输入输出样例
输入 #1复制
5 4 2 2 1 0 3 3 1 1 4 4 1 0 3 3 2 1
输出 #1复制
5 10 3 18 15 4 19 8 17 20 1 14 23 24 25 6 9 2 7 22 11 12 13 16 21
说明/提示
对于50%的数据,满足 r=1
对于100%的数据 1≤n,m≤500,满足 1≤x−r≤x+r≤n,1≤y−r≤y+r≤n。
#include<bits/stdc++.h>
using namespace std;
//小矩阵的左上角坐标为x,y,k阶方阵
void spin(vector<vector<int>>& matrix,int x,int y,int k,int z){vector<vector<int>> subMatrix(k,vector<int>(k));for(int i=0;i<k;i++){for(int j=0;j<k;j++)subMatrix[i][j]=matrix[x+i][y+j];}if(z==0){//顺时针旋转90度,先转置,按对角线交换元素,再反转每一行 for(int i=0;i<k;i++){for(int j=i;j<k;j++){swap(subMatrix[i][j],subMatrix[j][i]);}}//反转每一行元素 for(int i=0;i<k;i++){reverse(subMatrix[i].begin(),subMatrix[i].end());}//把旋转后的元素放回去 for(int i=0;i<k;i++){for(int j=0;j<k;j++){matrix[x+i][y+j]=subMatrix[i][j];}}}else if(z==1){//逆时针旋转90度,先反转行,在进行转置 for(int i=0;i<k;i++){reverse(subMatrix[i].begin(),subMatrix[i].end());}for(int i=0;i<k;i++){for(int j=i;j<k;j++){swap(subMatrix[i][j],subMatrix[j][i]);}} for(int i=0;i<k;i++){for(int j=0;j<k;j++){matrix[x+i][y+j]=subMatrix[i][j];}}}
}
int main(){int n,m;cin>>n>>m;vector<vector<int>> matrix(n,vector<int>(n)); int ans=1;for(int i=0;i<n;i++){for(int j=0;j<n;j++){matrix[i][j]=ans;ans++;}}int x,y,r,z;for(int i=0;i<m;i++){cin>>x>>y>>r>>z;spin(matrix,x-1-r,y-1-r,2*r+1,z);}for(int i=0;i<n;i++){for(int j=0;j<n;j++)cout<<matrix[i][j]<<" ";cout<<endl;}return 0;
}