数据结构
P1165 日志分析(栈的使用)
#include<vector>
#include<stack>
#include<iostream>
using namespace std;
//声明一个栈
stack<int> s;
int n;
int main(){
cin>>n;
int flag,w;
//推入一个元素
s.push(0);
for(int i=0;i<n;i++){
cin>>flag;
if(flag==0){
cin>>w;
//取出栈顶元素(但是不退栈)
int tmp = s.top();
if(w>tmp){
s.push(w);
}else{
s.push(tmp);
}
}else if(flag==1){
//求栈的大小
if(s.size()>1){
//退栈
s.pop();
}
}else if(flag==2){
cout<<s.top()<<endl;
}
}
return 0;
}
P3378 【模板】堆(priority的使用)
普通int类型
#include<iostream>
#include<queue>
using namespace std;
//第三个是函数 greater 大于号,前面的更大
//priority_queue<int,vector<int>,greater<int>> que;
//less小于号,前面更小
priority_queue<int,vector<int>,less<int>> que;
using namespace std;
int main(){
que.push(2);
que.push(1);
cout<<que.top();
return 0;
}
对结构体类型
#include<iostream>
#include<queue>
using namespace std;
typedef struct student{
int id;
int age;
bool operator < (const student &s)const{
return this->age<s.age;
}
}student;
priority_queue<student> que;
int main(){
student s1; s1.id=1;s1.age=28;
student s2; s2.id=2;s2.age=20;
que.push(s1); que.push(s2);
cout<<que.top().age;
return 0;
}
题目:
#include<iostream>
#include<queue>
using namespace std;
int n;
struct cmp{
bool operator () (int a,int b){
return a>b;
}
};
priority_queue<int,vector<int>,struct cmp> que;
int main(){
cin>>n;
for(int i=0;i<n;i++){
int flag;
cin>>flag;
if(flag==1){
int x;
cin>>x;
que.push(x);
}else if(flag==2){
cout<<que.top()<<endl;
}else if(flag==3){
que.pop();
}
}
return 0;
}
B3642 二叉树的遍历(模拟非指针)
#include<iostream>
using namespace std;
int n;
typedef struct Treenode{
int left,right;
Treenode(int left,int right){
this->left=left;
this->right=right;
}
Treenode(){
}
}Treenode;
Treenode *tree[100006];
void Preorder(int num){
if(num!=0){
cout<<num<<" ";
Preorder(tree[num]->left);
Preorder(tree[num]->right);
}
}
void Inorder(int num){
if(num!=0){
Inorder(tree[num]->left);
cout<<num<<" ";
Inorder(tree[num]->right);
}
}
void Afterorder(int num){
if(num!=0){
Afterorder(tree[num]->left);
Afterorder(tree[num]->right);
cout<<num<<" ";
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int left,right;
cin>>left>>right;
tree[i] = new Treenode();
tree[i]->left=left;
tree[i]->right=right;
}
Preorder(1);
cout<<endl;
Inorder(1);
cout<<endl;
Afterorder(1);
return 0;
}
P3366 【模板】最小生成树(最好使用krusal)
#include<iostream>
#include<algorithm>
//并查集 初始化为0 表示没有父节点
int arr[200005];
//边表
typedef struct node{
int i,j,w;
bool operator < (const node b) const{
return this->w<b.w;
}
}node;
node nodes[200005];
int n,m;
using namespace std;
int find(int num){
//父节点
if(arr[num]==num){
return num;
}else{
//路径压缩
int res =find(arr[num]);
arr[num]=res;
return res;
}
}
void merge(int a,int b){
int parent_a = find(a);
int parent_b = find(b);
if(parent_a!=parent_b){
//这里只是把b放到了a集合里
//应该是把b的父节点放在a集合里
//arr[b]=parent_a;
arr[parent_b]=parent_a;
}
}
int fun(int a,int b){
int parent_a = find(a);
int parent_b = find(b);
if(parent_a!=parent_b){
return 0;
}
return 1;
}
int main(){
cin>>n>>m;
//初始化
for(int i=0;i<=n;i++){
arr[i]=i;
}
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
node tmp;
tmp.i=x;
tmp.j=y;
tmp.w =z;
nodes[i]=tmp;
}
//排序
sort(nodes+1,nodes+m+1);
int sum=0,count=0;
//遍历所有的边
for(int i=1;i<=m;i++){
node tmp = nodes[i];
if(!fun(tmp.i,tmp.j)){
merge(tmp.i,tmp.j);
sum+=tmp.w;
count++;
}
}
if(count<n-1){
cout<<"orz";
}
cout<<sum;
return 0;
}
最短路径
#include<iostream>
//可以使用INT_MAX
#include<climits>
using namespace std;
int n,m,s;
int edges[1005][1005];
int dis[1005],vis[1005];
void djstar(){
for(int i=1;i<=n;i++){
dis[i] = INT_MAX;
vis[i] = 0;
}
vis[s]=1;
dis[s]=0;
for(int i=1;i<=n;i++){
if(edges[s][i]<dis[i]){
dis[i]=edges[s][i];
}
}
for(int i=0;i<n-1;i++){
int min=INT_MAX;
int minI=-1;
for(int j=1;j<=n;j++){
if(dis[j]<min&&vis[j]==0){
min = dis[j];
minI=j;
}
}
if(minI==-1) return;
vis[minI] = 1;
for(int j=1;j<=n;j++){
if(vis[j]==0&&dis[j]>dis[minI]+edges[minI][j]){
if(edges[minI][j]!=INT_MAX){
dis[j]=dis[minI]+edges[minI][j];
}
}
}
}
}
int main(){
cin>>n>>m>>s;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
edges[i][j]=INT_MAX;
}
}
for(int i=0;i<m;i++){
int u,v,w;
cin>>u>>v>>w;
if(edges[u][v]>w){
edges[u][v]=w;
}
}
djstar();
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
}
模拟
P1980 [NOIP 2013 普及组] 计数问题
[P1980 NOIP 2013 普及组] 计数问题 - 洛谷
#include<iostream>
#include<vector>
#define maxsize 1e6+7
int n,x;
std::vector<int> arr(maxsize);
void count(int num){
while(num){
arr[num%10]++;
num/=10;
}
}
int main(){
std::cin>>n>>x;
for(int i=1;i<=n;i++){
count(i);
}
std::cout<<arr[x];
return 0;
}
P1055 [NOIP 2008 普及组] ISBN 号码(基本string运算)
[P1055 NOIP 2008 普及组] ISBN 号码 - 洛谷
#include<iostream>
#include<string>
int main(){
std::string s;
std::cin>>s;
//生成纯数字的字符串
std::string tmp;
for(auto &i :s){
if(i!='-'){
tmp+=i;
}
}
//求和
int res=0;
for(int i=0;i<tmp.length()-1;i++){
res+=(tmp[i]-'0')*(i+1);
}
res= res%11;
if(res==10){
if(s[s.length()-1]=='X'){
std::cout<<"Right";
}else{
//输出s
for(int i=0;i<s.length()-1;i++){
std::cout<<s[i];
}
std::cout<<"X";
}
}else{
if(s[s.length()-1]==res+'0'){
std::cout<<"Right";
}else{
//输出s
for(int i=0;i<s.length()-1;i++){
std::cout<<s[i];
}
char c=res+'0';
std::cout<<c;
}
}
return 0;
}
基本字符串判断和运算
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main(){
string s ="1023456789";
//从0开始,包括0,一共截取3个
string tmp = s.substr(0,3);
cout<<tmp<<endl;
//这个find 如果返回了npos那么就是没有找到
cout<<tmp.find("10");
if(tmp.find("10")==string::npos){
cout<<"不存在";
}
if(isalpha(s[0])){
cout<<"是字母"<<endl;
}
if(isdigit(s[0])){
cout<<"是数字"<<endl;
}
if(isupper(s[0])){
cout<<"是大写"<<endl;
}
if(islower(s[0])){
cout<<"是小写"<<endl;
}
return 0;
}
P5015 [NOIP 2018 普及组] 标题统计
[P5015 NOIP 2018 普及组] 标题统计 - 洛谷
#include<iostream>
#include<vector>
#include<string>
#define maxsize 1e6+7
int main(){
std::string s;
//读入一行
std::getline(std::cin,s);
int count=0;
for(int i=0;i<s.length();i++){
if(s[i]!=' '){
count++;
}
}
std::cout<<count;
}
排序
#include<iostream>
#include<vector>
#include<algorithm>
int main(){
int n;
std::vector<int> arr;
std::cin>>n;
for(int i=0;i<n;i++){
int tmp;
std::cin>>tmp;
arr.push_back(tmp);
}
std::sort(arr.begin(),arr.end());
for(int i=0;i<n;i++){
std::cout<<arr[i]<<" ";
}
return 0;
}
//从大到小
#include<iostream>
#include<vector>
#include<algorithm>
bool cmp(int a,int b){
return a>b;
}
int main(){
int n;
std::vector<int> arr;
std::cin>>n;
for(int i=0;i<n;i++){
int tmp;
std::cin>>tmp;
arr.push_back(tmp);
}
std::sort(arr.begin(),arr.end(),cmp);
for(int i=0;i<n;i++){
std::cout<<arr[i]<<" ";
}
return 0;
}
快速排序(应用) sort函数
#include<iostream>
#include<algorithm>
using namespace std;
//快速排序
//1.定一个pivot,然后对数组进行一趟排序,排序完成后小于的放左边,否则放右边
//2.对左右子表,分别进行快速排序,最后等到左右子表只有一个元素的时候排序结束
int partition(int arr[],int left,int right){
//pivot不是arr[0]
int pivot =arr[left];
while(left<right){
//while循环里一定要带left<right
while(left<right&&arr[right]>=pivot) right--;
//从右边拿元素到左边
arr[left]=arr[right];
while(left<right&&arr[left]<=pivot) left++;
//从左边拿元素到右边
arr[right]=arr[left];
}
arr[left]=pivot;
return left;
}
void QuickSort(int arr[],int left,int right){
if(left<right){
int middle=partition(arr,left,right);
for(int i=0;i<10;i++){
cout<<arr[i]<<" ";
}
cout<<endl;
QuickSort(arr,left,middle-1);
QuickSort(arr,middle+1,right);
}
}
int main(){
int arr[]={6,8,7,9,0,1,3,2,4,5};//测试数据
//int arr[]={49,38,65,97,76,13,27,49};//测试数据
//int arr[]={29,18,25,47,58,12,51,10};//测试数据
QuickSort(arr,0,9);
}
归并排序(应用)
求逆序对(mid-i+1)
#include<iostream>
using namespace std;
long long sum=0;
int arr[500007];
int tmp[500007];
int n;
void merge(int begin,int end){
int mid = (begin+end)/2;
int count = begin;
//i要从begin开始 j要从mid+1开始
int i=begin,j=mid+1;
for(;i<=mid&&j<=end;){
if(arr[i]<=arr[j]){
tmp[count++]=arr[i++];
}else{
//计算逆序对
sum+=mid-i+1;
tmp[count++]=arr[j++];
}
}
while(i<=mid){
tmp[count++]=arr[i++];
}
while(j<=end){
tmp[count++]=arr[j++];
}
for(int i=begin;i<=end;i++){
arr[i]=tmp[i];
}
}
void sort(int b,int e){
if(b<e){
int mid = (b+e)/2;
sort(b,mid);
sort(mid+1,e);
merge(b,e);
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
sort(0,n-1);
cout<<sum<<endl;
return 0;
}
数的划分
数的划分 - 洛谷 P1025 - Virtual Judge
#include <iostream>
#define maxsize 1000
int dp[maxsize][maxsize]={0};
//dp[i][j] 表示把i分成j份有多少次
int n,k;
int main() {
std::cin>>n>>k;
//将0分成0份有1种方式 初始化
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
//分成第一份是1,第二份不是1
//第一份是1 dp[i-1][j-1]
//第一份不是1,就每个分一个1,然后再分dp[i-j][j]
if(i>=j){
//一种先分一个位置是1 其他再分 dp[i-1][j-1](至少有一个1)
//一种每个位置先分一个1,再分 dp[i-j][j](一个1都没有)
dp[i][j] = dp[i-1][j-1] + dp[i-j][j];
}
}
}
std::cout<<dp[n][k];
return 0;
}
P1024 [NOIP 2001 提高组] 一元三次方程求解
[P1024 NOIP 2001 提高组] 一元三次方程求解 - 洛谷
遍历所有的解,当函数值不同号时,取平均值
#include <iostream>
#include <cmath>
using namespace std;
double a, b, c, d;
double f(double i){
return i*i*i*a+b*i*i+c*i+d;
}
int main() {
cin>>a>>b>>c>>d;
for(double i=-100.00;i<100.00;i+=0.01){
double j=i+0.01;
double y1=f(i);
double y2=f(j);
if(y1*y2<0){
printf("%.2lf ",(i+j)/2);
}
}
return 0;
}
P1421 小玉买文具(进制转换)
#include<iostream>
using namespace std;
//全都转化为十进制做除法
int a,b;
int main(){
cin>>a>>b;
int sum=0;
sum+=a*10;
sum+=b;
cout<<sum/19;
return 0;
}
P6382 『MdOI R2』Car(常见字符串的识别题目)
第三次训练 - Virtual JudgeP6382 『MdOI R2』Car - 洛谷
#include<iostream>
using namespace std;
string s;
int getnum(){
for(int i=s.length()-1;i>=0;i--){
if(isdigit(s[i])){
return s[i]-'0';
}
}
}
int main(){
cin>>s;
//截取字符串
string flag = s.substr(0,3);
if(flag=="MDA"){
//字符传化
int num = getnum();
for(int i=1;i<=5;i++){
if(i==5){
if(num==5||num==0){
cout<<1<<" ";
} else{
cout<<0<<" ";
}
break;
}
if(num==i||num==10-i){
cout<<1<<" ";
}else{
cout<<0<<" ";
}
}
}else{
for(int i=0;i<=4;i++){
cout<<"1"<<" ";
}
}
return 0;
}
P1143 进制转换
#include<iostream>
#include<string>
#include<cctype>
#include<cmath>
//一开始和最后的进制
int begin,end;
std::string s;
int main(){
std::cin>>begin;
std::cin>>s;
std::cin>>end;
//转化为十进制
int sum=0;
//每一位的权值 (通过权值传化为十进制)
int level_power=0;
for(int i=s.length()-1; i >=0;i--){
//每一位的数码
int num=0;
if(std::isupper(s[i])){
num = s[i]-'A';
num+=10;
}else{
num = s[i]-'0';
}
int tmp = num*pow(begin,level_power);
level_power++;
sum+= tmp;
}
//通过求余把十进制转化为其他的进制
s="";
if(end==10){
std::cout<<sum;
}else{
//进行转化
int stack[10000];
int j=0;
while(sum){
stack[j++]=sum%end;
//更新sum
sum/=end;
}
//最后j++到最后的这个地方并没有更新数据
j--;
while(j>=0){
if(stack[j]>=10){
int tmp = stack[j]%10;
char c = 'A'+tmp;
s+=c;
}else{
char c = '0' + stack[j];
s+=c;
}
j--;
}
std::cout<<s;
}
return 0;
}
P1425 小鱼的游泳时间(时间类的转化为进制问题)
#include<iostream>
#include<string>
#include<cctype>
#include<cmath>
int a,b,c,d;
int main(){
std::cin>>a>>b>>c>>d;
//用进制 60进制 也就是全部有多少分钟
int num1 = a*60+b;
int num2 = c*60+d;
int res = num2-num1;
std::cout<<res/60<<" "<<res%60;
return 0;
}
P1553 数字反转(学习一些字符串处理函数)
#include<iostream>
#include<algorithm>
using namespace std;
string s;
//删除字符串中的后置0
void trim(string &s){
while(s.back()=='0'&&s.length()>1){
//后置删除 s.erase(s.begin(),3) str.erase(0,3)
s.pop_back();
}
reverse(s.begin(),s.end());
}
int main(){
int final = 0;
cin>>s;
if(s[s.length()-1]=='%'){
final=1;
s.pop_back();
trim(s);
cout<<s<<"%";
}
int flag_xiaoshu = s.find(".");
if(flag_xiaoshu!=-1){
final=1;
//裁剪
string before=s.substr(0,flag_xiaoshu);
trim(before);
cout<<before;
cout<<".";
string after = s.substr(flag_xiaoshu+1,s.length()-flag_xiaoshu+1);
trim(after);
//这里最后也需要裁剪一下
while(after.back()=='0'&&after.length()>1){
after.pop_back();
}
cout<<after;
}
int flag = s.find("/");
if(flag!=-1){
final=1;
//裁剪
string before=s.substr(0,flag);
trim(before);
cout<<before;
cout<<"/";
string after = s.substr(flag+1,s.length()-flag+1);
trim(after);
//这里最后也需要裁剪一下
while(after.back()=='0'&&after.length()>1){
after.pop_back();
}
cout<<after;
}
if(final==0){
trim(s);
cout<<s;
}
return 0;
}
P8651 [蓝桥杯 2017 省 B] 日期问题(格式输出)
[P8651 蓝桥杯 2017 省 B] 日期问题 - 洛谷
日期类的核心
1.遍历所有的日期
2.闰年的判断
3.月份31天, 闰年2月有29天 否则28天
#include<iostream>
#include<string>
using namespace std;
string s;
int days[]={0,31,27,31,30,31,30,31,31,30,31,30,31};
int main(){
cin>>s;
int r_year = stoi(s.substr(0,2));
int r_month = stoi(s.substr(3,2));
int r_day = stoi(s.substr(6,2));
for(int year = 1960; year<=2059;year++){
int flag =0;
//世纪闰年
if(year%400==0){
flag =1;
//普通闰年
}else if(year%4==0&&year%100!=0){
flag =1;
}
if(flag == 1){
days[2]=29;
}else{
days[2]=28;
}
for(int month=1;month<=12;month++){
for(int day=1;day<=days[month];day++){
if(year%100==r_year&&r_month==month&&r_day==day){
//输出格式规定
printf("%d-%02d-%02d\n",year,month,day);
}
if(year%100==r_day&&month==r_year&&day==r_month){
//输出格式规定
printf("%d-%02d-%02d\n",year,month,day);
}
if(year%100==r_day&&month==r_month&&day==r_year){
//输出格式规定
printf("%d-%02d-%02d\n",year,month,day);
}
}
}
}
return 0;
}
P2074 危险区域
1.不是BFS而是直接计算距离
#include<iostream>
#include<cmath>
using namespace std;
int n,m,k,t;
int count =0;
int res = -1;
//计算距离
double distance(int x1,int y1,int x2,int y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main(){
cin>>n>>m>>k>>t;
//用正方形框柱圆圈
for(int i=0;i<k;i++){
int x0,y0;
cin>>x0>>y0;
//画正方形
for(int r=max(1,x0-t);r<=min(n,x0+t);r++){
for(int c=max(1,y0-t);c<=min(n,y0+t);c++){
if(distance(x0,y0,r,c)<=t){
count++;
}
}
}
res=max(res,count);
count =0;
}
cout<<res;
return 0;
}
DFS BFS搜索类
记忆化DFS
滑雪
期末最终测试 - Virtual Judge SHOI2002] 滑雪 - 洛谷
1.滑雪必须从高往下滑,所以不会有vis数组,因为不可能重新滑回来
2.当我们寻找一个最长路径的时候必须9->8->7->6是一个最长路径时,8的最长路径就已经确定了8->7->6
#include<iostream>
using namespace std;
//dfs遍历数组
int direction_x[]={-1,1,0,0};
int direction_y[]={0,0,-1,1};
int dp[107][107];
int map[107][107];
int r,c;
int res=-1;
int check(int x,int y){
if(x<=0||x>r||y<=0||y>c){
return 0;
}
return 1;
}
//返回i,j的最长路径
int dfs(int i,int j){
//如果当前搜索过
if(dp[i][j]!=0){
return dp[i][j];
}else{
//没搜索过 =1 开始搜索
dp[i][j]=1;
for(int k=0;k<4;k++){
int x=i+direction_x[k];
int y=j+direction_y[k];
if(check(x,y)&&map[x][y]<map[i][j]){
dp[i][j]=max(dp[i][j],dfs(x,y)+1);
}
}
}
return dp[i][j];
}
int main(){
cin>>r>>c;
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
cin>>map[i][j];
}
}
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
//保存所有节点的最长路径
res = max(res,dfs(i,j));
}
}
cout<<res;
return 0;
}
普通DFS
P1162 填涂颜色
换个思路找圈子内难,但是圈子外,加上一行用DFS可以全部遍历,通过visit判断是否走完
#include<iostream>
int n,matrix[37][37],visit[37][37];
int direction_x[] = {0,0,-1,1};;
int direction_y[]= {1,-1,0,0};
void dfs(int i,int j){
if(visit[i][j]==1||matrix[i][j]==1||i<0||i>n+1||j<0||j>n+1) return;
else{
visit[i][j]=1;
for(int k=0;k<4;k++){
dfs(i+direction_x[k],j+direction_y[k]);
}
}
}
int main(){
std::cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
std::cin>>matrix[i][j];
}
}
//找到第一个0
for(int i=0;i<=n+1;i++){
if(matrix[0][i]==0){
dfs(0,i);
break;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(matrix[i][j]==1){
std::cout<<matrix[i][j]<<" ";
}else{
if(visit[i][j]==0){
std::cout<<2<<" ";
}else{
std::cout<<0<<" ";
}
}
}
std::cout<<std::endl;
}
return 0;
}
P1706 全排列问题
#include<iostream>
#define maxsize 10005
#include<iomanip>
#include<vector>
using namespace std;
int n;
int visit[maxsize];
vector<int> arr;
void dfs(int i){
if(i>n){
for(int j=0;j<n;j++){
cout<<setw(5)<<arr[j];
}
cout<<endl;
}else{
for(int j=1;j<=n;j++){
//没有被选中
if(visit[j]==0){
visit[j]=1;
arr.push_back(j);
dfs(i+1);
arr.pop_back();
visit[j]=0;
}
}
}
}
int main(){
cin>>n;
dfs(1);
return 0;
}
P2089 烤鸡
1-3个数 然后全排列
#include<iostream>
#include<vector>
using namespace std;
int res=0;
int n;
int arr_res[50000][12];
vector<int> arr;
void dfs(int i){
if(i>=10){
int sum=0;
for(int j=0;j<arr.size();j++){
sum+=arr[j];
}
if(sum==n){
for(int j=0;j<arr.size();j++){
arr_res[res][j]=arr[j];
}
res++;
}
}else{
for(int j=1;j<=3;j++){
arr.push_back(j);
dfs(i+1);
arr.pop_back();
}
}
}
int main(){
cin>>n;
dfs(0);
cout<<res<<endl;
for(int i=0;i<res;i++){
for(int j=0;j<10;j++){
cout<<arr_res[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
P1219 [USACO1.5] 八皇后 Checker Challenge
第三次训练 - Virtual Judge[P1219 USACO1.5] 八皇后 Checker Challenge - 洛谷
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int n;
int res = 0;
int arr_res[20][20];
vector<int> arr;
bool check(int i,int j){
int x=0;
for(auto num: arr){
if(num==j){
return false;
}
if(abs(x-i)==abs(j-num)){
return false;
}
x++;
}
return true;
}
void dfs(int i){
if(i>=n){
//输出前三个解
if(res<3){
for(int j=0;j<n;j++){
arr_res[res][j] = arr[j];
}
}
res++;
}else{
for(int j=0;j<n;j++){
if(check(i,j)){
arr.push_back(j);
dfs(i+1);
arr.pop_back();
}
}
}
}
int main(){
cin>>n;
dfs(0);
for(int i=0;i<3;i++){
for(int j=0;j<n;j++){
//由于前面是从0开始的,所以这里要+1
cout<<arr_res[i][j]+1<<" ";
}
cout<<endl;
}
cout<<res;
return 0;
}
动态规划
P1059 [NOIP 2006 普及组] 明明的随机数(去重,排序想到set)
[P1059 NOIP 2006 普及组] 明明的随机数 - 洛谷
#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
vector<int> arr(1e6);
set<int> res;
int n;
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
int cnt=0;
for(int i=0;i<n;i++){
res.insert(arr[i]);
}
cout<<res.size()<<endl;
for(auto it : res){
cout<<it<<" ";
}
}
P1739 表达式括号匹配
#include<iostream>
#include<string>
using namespace std;
string s;
int main(){
cin>>s;
s.pop_back();
int top=-1;
char stack[1000000];
int cnt=0;
for(auto c : s){
//左括号进栈
if(c=='('){
stack[++top]=c;
}else if(c==')'){
//栈不能为空,并且必须是(
if(top==-1){
cout<<"NO";
return 0;
}else{
char tmp_c = stack[top--];
if(tmp_c!='('){
cout<<"NO";
return 0;
}
}
}
}
//栈为空
if(top==-1){
cout<<"YES";
}else{
cout<<"NO";
}
return 0;
}
U225269 01背包问题
#include<iostream>
#include<vector>
using namespace std;
vector<int> arr_v(1e6);
vector<int> arr_w(1e6);
int dp[5000][5000]={0},V,N;
int main(){
cin>>V>>N;
for(int i=1;i<=N;i++){
cin>>arr_v[i]>>arr_w[i];
}
for(int i=1;i<=N;i++){
for(int j=1;j<=V;j++){
if(arr_v[i]<=j){
dp[i][j] = max(dp[i-1][j],dp[i-1][j-arr_v[i]]+arr_w[i]);
}else{
dp[i][j]=dp[i-1][j];
}
}
}
cout<<dp[N][V];
}
P1049 [NOIP 2001 普及组] 装箱问题(01背包问题的变种)
[P1049 NOIP 2001 普及组] 装箱问题 - 洛谷
#include<iostream>
#include<vector>
using namespace std;
vector<int> arr_w(1e6);
int dp[31][20007]={0},V,N;
int main(){
cin>>V;
cin>>N;
for(int i=1;i<=N;i++){
cin>>arr_w[i];
}
for(int i=1;i<=N;i++){
for(int j=1;j<=V;j++){
if(arr_w[i]<=j){
dp[i][j] = max(dp[i-1][j],dp[i-1][j-arr_w[i]]+arr_w[i]);
}else{
dp[i][j]=dp[i-1][j];
}
}
}
cout<<V-dp[N][V];
}
P1115 最大子段和
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int n,dp[1000000];
vector<int> arr;
int main(){
cin>>n;
for(int i=0;i<n;i++){
int tmp;
cin>>tmp;
arr.push_back(tmp);
}
//初始化
dp[0]=arr[0];
for(int i=1;i<n;i++){
//当前值,或者前面值+1
dp[i] = max(arr[i],dp[i-1]+arr[i]);
}
int max = dp[0];
for(int i=1;i<n;i++){
if(dp[i]>max){
max = dp[i];
}
}
cout<<max;
return 0;
}
P1439 【模板】最长公共子序列
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int n,dp[100000][100000];
vector<int> arr_1(10007),arr_2(10007);
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr_1[i];
}
for(int i=1;i<=n;i++){
cin>>arr_2[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(arr_1[i]==arr_2[j]){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
}
int res = -1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
res = max(res,dp[i][j]);
}
}
cout<<res;
return 0;
}
数据结构
P1165 日志分析(栈的使用)
#include<vector>
#include<stack>
#include<iostream>
using namespace std;
//声明一个栈
stack<int> s;
int n;
int main(){
cin>>n;
int flag,w;
//推入一个元素
s.push(0);
for(int i=0;i<n;i++){
cin>>flag;
if(flag==0){
cin>>w;
//取出栈顶元素(但是不退栈)
int tmp = s.top();
if(w>tmp){
s.push(w);
}else{
s.push(tmp);
}
}else if(flag==1){
//求栈的大小
if(s.size()>1){
//退栈
s.pop();
}
}else if(flag==2){
cout<<s.top()<<endl;
}
}
return 0;
}
P3378 【模板】堆(priority的使用)
普通int类型
#include<iostream>
#include<queue>
using namespace std;
//第三个是函数 greater 大于号,前面的更大
//priority_queue<int,vector<int>,greater<int>> que;
//less小于号,前面更小
priority_queue<int,vector<int>,less<int>> que;
using namespace std;
int main(){
que.push(2);
que.push(1);
cout<<que.top();
return 0;
}
对结构体类型
#include<iostream>
#include<queue>
using namespace std;
typedef struct student{
int id;
int age;
bool operator < (const student &s)const{
return this->age<s.age;
}
}student;
priority_queue<student> que;
int main(){
student s1; s1.id=1;s1.age=28;
student s2; s2.id=2;s2.age=20;
que.push(s1); que.push(s2);
cout<<que.top().age;
return 0;
}
题目:
#include<iostream>
#include<queue>
using namespace std;
int n;
struct cmp{
bool operator () (int a,int b){
return a>b;
}
};
priority_queue<int,vector<int>,struct cmp> que;
int main(){
cin>>n;
for(int i=0;i<n;i++){
int flag;
cin>>flag;
if(flag==1){
int x;
cin>>x;
que.push(x);
}else if(flag==2){
cout<<que.top()<<endl;
}else if(flag==3){
que.pop();
}
}
return 0;
}
B3642 二叉树的遍历(模拟非指针)
#include<iostream>
using namespace std;
int n;
typedef struct Treenode{
int left,right;
Treenode(int left,int right){
this->left=left;
this->right=right;
}
Treenode(){
}
}Treenode;
Treenode *tree[100006];
void Preorder(int num){
if(num!=0){
cout<<num<<" ";
Preorder(tree[num]->left);
Preorder(tree[num]->right);
}
}
void Inorder(int num){
if(num!=0){
Inorder(tree[num]->left);
cout<<num<<" ";
Inorder(tree[num]->right);
}
}
void Afterorder(int num){
if(num!=0){
Afterorder(tree[num]->left);
Afterorder(tree[num]->right);
cout<<num<<" ";
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int left,right;
cin>>left>>right;
tree[i] = new Treenode();
tree[i]->left=left;
tree[i]->right=right;
}
Preorder(1);
cout<<endl;
Inorder(1);
cout<<endl;
Afterorder(1);
return 0;
}
P3366 【模板】最小生成树(最好使用krusal)
#include<iostream>
#include<algorithm>
//并查集 初始化为0 表示没有父节点
int arr[200005];
//边表
typedef struct node{
int i,j,w;
bool operator < (const node b) const{
return this->w<b.w;
}
}node;
node nodes[200005];
int n,m;
using namespace std;
int find(int num){
//父节点
if(arr[num]==num){
return num;
}else{
//路径压缩
int res =find(arr[num]);
arr[num]=res;
return res;
}
}
void merge(int a,int b){
int parent_a = find(a);
int parent_b = find(b);
if(parent_a!=parent_b){
//这里只是把b放到了a集合里
//应该是把b的父节点放在a集合里
//arr[b]=parent_a;
arr[parent_b]=parent_a;
}
}
int fun(int a,int b){
int parent_a = find(a);
int parent_b = find(b);
if(parent_a!=parent_b){
return 0;
}
return 1;
}
int main(){
cin>>n>>m;
//初始化
for(int i=0;i<=n;i++){
arr[i]=i;
}
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
node tmp;
tmp.i=x;
tmp.j=y;
tmp.w =z;
nodes[i]=tmp;
}
//排序
sort(nodes+1,nodes+m+1);
int sum=0,count=0;
//遍历所有的边
for(int i=1;i<=m;i++){
node tmp = nodes[i];
if(!fun(tmp.i,tmp.j)){
merge(tmp.i,tmp.j);
sum+=tmp.w;
count++;
}
}
if(count<n-1){
cout<<"orz";
}
cout<<sum;
return 0;
}
最短路径
#include<iostream>
//可以使用INT_MAX
#include<climits>
using namespace std;
int n,m,s;
int edges[1005][1005];
int dis[1005],vis[1005];
void djstar(){
for(int i=1;i<=n;i++){
dis[i] = INT_MAX;
vis[i] = 0;
}
vis[s]=1;
dis[s]=0;
for(int i=1;i<=n;i++){
if(edges[s][i]<dis[i]){
dis[i]=edges[s][i];
}
}
for(int i=0;i<n-1;i++){
int min=INT_MAX;
int minI=-1;
for(int j=1;j<=n;j++){
if(dis[j]<min&&vis[j]==0){
min = dis[j];
minI=j;
}
}
if(minI==-1) return;
vis[minI] = 1;
for(int j=1;j<=n;j++){
if(vis[j]==0&&dis[j]>dis[minI]+edges[minI][j]){
if(edges[minI][j]!=INT_MAX){
dis[j]=dis[minI]+edges[minI][j];
}
}
}
}
}
int main(){
cin>>n>>m>>s;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
edges[i][j]=INT_MAX;
}
}
for(int i=0;i<m;i++){
int u,v,w;
cin>>u>>v>>w;
if(edges[u][v]>w){
edges[u][v]=w;
}
}
djstar();
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
}
模拟
P1980 [NOIP 2013 普及组] 计数问题
[P1980 NOIP 2013 普及组] 计数问题 - 洛谷
#include<iostream>
#include<vector>
#define maxsize 1e6+7
int n,x;
std::vector<int> arr(maxsize);
void count(int num){
while(num){
arr[num%10]++;
num/=10;
}
}
int main(){
std::cin>>n>>x;
for(int i=1;i<=n;i++){
count(i);
}
std::cout<<arr[x];
return 0;
}
P1055 [NOIP 2008 普及组] ISBN 号码(基本string运算)
[P1055 NOIP 2008 普及组] ISBN 号码 - 洛谷
#include<iostream>
#include<string>
int main(){
std::string s;
std::cin>>s;
//生成纯数字的字符串
std::string tmp;
for(auto &i :s){
if(i!='-'){
tmp+=i;
}
}
//求和
int res=0;
for(int i=0;i<tmp.length()-1;i++){
res+=(tmp[i]-'0')*(i+1);
}
res= res%11;
if(res==10){
if(s[s.length()-1]=='X'){
std::cout<<"Right";
}else{
//输出s
for(int i=0;i<s.length()-1;i++){
std::cout<<s[i];
}
std::cout<<"X";
}
}else{
if(s[s.length()-1]==res+'0'){
std::cout<<"Right";
}else{
//输出s
for(int i=0;i<s.length()-1;i++){
std::cout<<s[i];
}
char c=res+'0';
std::cout<<c;
}
}
return 0;
}
基本字符串判断和运算
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main(){
string s ="1023456789";
//从0开始,包括0,一共截取3个
string tmp = s.substr(0,3);
cout<<tmp<<endl;
//这个find 如果返回了npos那么就是没有找到
cout<<tmp.find("10");
if(tmp.find("10")==string::npos){
cout<<"不存在";
}
if(isalpha(s[0])){
cout<<"是字母"<<endl;
}
if(isdigit(s[0])){
cout<<"是数字"<<endl;
}
if(isupper(s[0])){
cout<<"是大写"<<endl;
}
if(islower(s[0])){
cout<<"是小写"<<endl;
}
return 0;
}
P5015 [NOIP 2018 普及组] 标题统计
[P5015 NOIP 2018 普及组] 标题统计 - 洛谷
#include<iostream>
#include<vector>
#include<string>
#define maxsize 1e6+7
int main(){
std::string s;
//读入一行
std::getline(std::cin,s);
int count=0;
for(int i=0;i<s.length();i++){
if(s[i]!=' '){
count++;
}
}
std::cout<<count;
}
排序
#include<iostream>
#include<vector>
#include<algorithm>
int main(){
int n;
std::vector<int> arr;
std::cin>>n;
for(int i=0;i<n;i++){
int tmp;
std::cin>>tmp;
arr.push_back(tmp);
}
std::sort(arr.begin(),arr.end());
for(int i=0;i<n;i++){
std::cout<<arr[i]<<" ";
}
return 0;
}
//从大到小
#include<iostream>
#include<vector>
#include<algorithm>
bool cmp(int a,int b){
return a>b;
}
int main(){
int n;
std::vector<int> arr;
std::cin>>n;
for(int i=0;i<n;i++){
int tmp;
std::cin>>tmp;
arr.push_back(tmp);
}
std::sort(arr.begin(),arr.end(),cmp);
for(int i=0;i<n;i++){
std::cout<<arr[i]<<" ";
}
return 0;
}
快速排序(应用) sort函数
#include<iostream>
#include<algorithm>
using namespace std;
//快速排序
//1.定一个pivot,然后对数组进行一趟排序,排序完成后小于的放左边,否则放右边
//2.对左右子表,分别进行快速排序,最后等到左右子表只有一个元素的时候排序结束
int partition(int arr[],int left,int right){
//pivot不是arr[0]
int pivot =arr[left];
while(left<right){
//while循环里一定要带left<right
while(left<right&&arr[right]>=pivot) right--;
//从右边拿元素到左边
arr[left]=arr[right];
while(left<right&&arr[left]<=pivot) left++;
//从左边拿元素到右边
arr[right]=arr[left];
}
arr[left]=pivot;
return left;
}
void QuickSort(int arr[],int left,int right){
if(left<right){
int middle=partition(arr,left,right);
for(int i=0;i<10;i++){
cout<<arr[i]<<" ";
}
cout<<endl;
QuickSort(arr,left,middle-1);
QuickSort(arr,middle+1,right);
}
}
int main(){
int arr[]={6,8,7,9,0,1,3,2,4,5};//测试数据
//int arr[]={49,38,65,97,76,13,27,49};//测试数据
//int arr[]={29,18,25,47,58,12,51,10};//测试数据
QuickSort(arr,0,9);
}
归并排序(应用)
求逆序对(mid-i+1)
#include<iostream>
using namespace std;
long long sum=0;
int arr[500007];
int tmp[500007];
int n;
void merge(int begin,int end){
int mid = (begin+end)/2;
int count = begin;
//i要从begin开始 j要从mid+1开始
int i=begin,j=mid+1;
for(;i<=mid&&j<=end;){
if(arr[i]<=arr[j]){
tmp[count++]=arr[i++];
}else{
//计算逆序对
sum+=mid-i+1;
tmp[count++]=arr[j++];
}
}
while(i<=mid){
tmp[count++]=arr[i++];
}
while(j<=end){
tmp[count++]=arr[j++];
}
for(int i=begin;i<=end;i++){
arr[i]=tmp[i];
}
}
void sort(int b,int e){
if(b<e){
int mid = (b+e)/2;
sort(b,mid);
sort(mid+1,e);
merge(b,e);
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
sort(0,n-1);
cout<<sum<<endl;
return 0;
}
数的划分
数的划分 - 洛谷 P1025 - Virtual Judge
#include <iostream>
#define maxsize 1000
int dp[maxsize][maxsize]={0};
//dp[i][j] 表示把i分成j份有多少次
int n,k;
int main() {
std::cin>>n>>k;
//将0分成0份有1种方式 初始化
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
//分成第一份是1,第二份不是1
//第一份是1 dp[i-1][j-1]
//第一份不是1,就每个分一个1,然后再分dp[i-j][j]
if(i>=j){
//一种先分一个位置是1 其他再分 dp[i-1][j-1](至少有一个1)
//一种每个位置先分一个1,再分 dp[i-j][j](一个1都没有)
dp[i][j] = dp[i-1][j-1] + dp[i-j][j];
}
}
}
std::cout<<dp[n][k];
return 0;
}
P1024 [NOIP 2001 提高组] 一元三次方程求解
[P1024 NOIP 2001 提高组] 一元三次方程求解 - 洛谷
遍历所有的解,当函数值不同号时,取平均值
#include <iostream>
#include <cmath>
using namespace std;
double a, b, c, d;
double f(double i){
return i*i*i*a+b*i*i+c*i+d;
}
int main() {
cin>>a>>b>>c>>d;
for(double i=-100.00;i<100.00;i+=0.01){
double j=i+0.01;
double y1=f(i);
double y2=f(j);
if(y1*y2<0){
printf("%.2lf ",(i+j)/2);
}
}
return 0;
}
P1421 小玉买文具(进制转换)
#include<iostream>
using namespace std;
//全都转化为十进制做除法
int a,b;
int main(){
cin>>a>>b;
int sum=0;
sum+=a*10;
sum+=b;
cout<<sum/19;
return 0;
}
P6382 『MdOI R2』Car(常见字符串的识别题目)
第三次训练 - Virtual JudgeP6382 『MdOI R2』Car - 洛谷
#include<iostream>
using namespace std;
string s;
int getnum(){
for(int i=s.length()-1;i>=0;i--){
if(isdigit(s[i])){
return s[i]-'0';
}
}
}
int main(){
cin>>s;
//截取字符串
string flag = s.substr(0,3);
if(flag=="MDA"){
//字符传化
int num = getnum();
for(int i=1;i<=5;i++){
if(i==5){
if(num==5||num==0){
cout<<1<<" ";
} else{
cout<<0<<" ";
}
break;
}
if(num==i||num==10-i){
cout<<1<<" ";
}else{
cout<<0<<" ";
}
}
}else{
for(int i=0;i<=4;i++){
cout<<"1"<<" ";
}
}
return 0;
}
P1143 进制转换
#include<iostream>
#include<string>
#include<cctype>
#include<cmath>
//一开始和最后的进制
int begin,end;
std::string s;
int main(){
std::cin>>begin;
std::cin>>s;
std::cin>>end;
//转化为十进制
int sum=0;
//每一位的权值 (通过权值传化为十进制)
int level_power=0;
for(int i=s.length()-1; i >=0;i--){
//每一位的数码
int num=0;
if(std::isupper(s[i])){
num = s[i]-'A';
num+=10;
}else{
num = s[i]-'0';
}
int tmp = num*pow(begin,level_power);
level_power++;
sum+= tmp;
}
//通过求余把十进制转化为其他的进制
s="";
if(end==10){
std::cout<<sum;
}else{
//进行转化
int stack[10000];
int j=0;
while(sum){
stack[j++]=sum%end;
//更新sum
sum/=end;
}
//最后j++到最后的这个地方并没有更新数据
j--;
while(j>=0){
if(stack[j]>=10){
int tmp = stack[j]%10;
char c = 'A'+tmp;
s+=c;
}else{
char c = '0' + stack[j];
s+=c;
}
j--;
}
std::cout<<s;
}
return 0;
}
P1425 小鱼的游泳时间(时间类的转化为进制问题)
#include<iostream>
#include<string>
#include<cctype>
#include<cmath>
int a,b,c,d;
int main(){
std::cin>>a>>b>>c>>d;
//用进制 60进制 也就是全部有多少分钟
int num1 = a*60+b;
int num2 = c*60+d;
int res = num2-num1;
std::cout<<res/60<<" "<<res%60;
return 0;
}
P1553 数字反转(学习一些字符串处理函数)
#include<iostream>
#include<algorithm>
using namespace std;
string s;
//删除字符串中的后置0
void trim(string &s){
while(s.back()=='0'&&s.length()>1){
//后置删除 s.erase(s.begin(),3) str.erase(0,3)
s.pop_back();
}
reverse(s.begin(),s.end());
}
int main(){
int final = 0;
cin>>s;
if(s[s.length()-1]=='%'){
final=1;
s.pop_back();
trim(s);
cout<<s<<"%";
}
int flag_xiaoshu = s.find(".");
if(flag_xiaoshu!=-1){
final=1;
//裁剪
string before=s.substr(0,flag_xiaoshu);
trim(before);
cout<<before;
cout<<".";
string after = s.substr(flag_xiaoshu+1,s.length()-flag_xiaoshu+1);
trim(after);
//这里最后也需要裁剪一下
while(after.back()=='0'&&after.length()>1){
after.pop_back();
}
cout<<after;
}
int flag = s.find("/");
if(flag!=-1){
final=1;
//裁剪
string before=s.substr(0,flag);
trim(before);
cout<<before;
cout<<"/";
string after = s.substr(flag+1,s.length()-flag+1);
trim(after);
//这里最后也需要裁剪一下
while(after.back()=='0'&&after.length()>1){
after.pop_back();
}
cout<<after;
}
if(final==0){
trim(s);
cout<<s;
}
return 0;
}
P8651 [蓝桥杯 2017 省 B] 日期问题(格式输出)
[P8651 蓝桥杯 2017 省 B] 日期问题 - 洛谷
日期类的核心
1.遍历所有的日期
2.闰年的判断
3.月份31天, 闰年2月有29天 否则28天
#include<iostream>
#include<string>
using namespace std;
string s;
int days[]={0,31,27,31,30,31,30,31,31,30,31,30,31};
int main(){
cin>>s;
int r_year = stoi(s.substr(0,2));
int r_month = stoi(s.substr(3,2));
int r_day = stoi(s.substr(6,2));
for(int year = 1960; year<=2059;year++){
int flag =0;
//世纪闰年
if(year%400==0){
flag =1;
//普通闰年
}else if(year%4==0&&year%100!=0){
flag =1;
}
if(flag == 1){
days[2]=29;
}else{
days[2]=28;
}
for(int month=1;month<=12;month++){
for(int day=1;day<=days[month];day++){
if(year%100==r_year&&r_month==month&&r_day==day){
//输出格式规定
printf("%d-%02d-%02d\n",year,month,day);
}
if(year%100==r_day&&month==r_year&&day==r_month){
//输出格式规定
printf("%d-%02d-%02d\n",year,month,day);
}
if(year%100==r_day&&month==r_month&&day==r_year){
//输出格式规定
printf("%d-%02d-%02d\n",year,month,day);
}
}
}
}
return 0;
}
P2074 危险区域
1.不是BFS而是直接计算距离
#include<iostream>
#include<cmath>
using namespace std;
int n,m,k,t;
int count =0;
int res = -1;
//计算距离
double distance(int x1,int y1,int x2,int y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main(){
cin>>n>>m>>k>>t;
//用正方形框柱圆圈
for(int i=0;i<k;i++){
int x0,y0;
cin>>x0>>y0;
//画正方形
for(int r=max(1,x0-t);r<=min(n,x0+t);r++){
for(int c=max(1,y0-t);c<=min(n,y0+t);c++){
if(distance(x0,y0,r,c)<=t){
count++;
}
}
}
res=max(res,count);
count =0;
}
cout<<res;
return 0;
}
DFS BFS搜索类
记忆化DFS
滑雪
期末最终测试 - Virtual Judge SHOI2002] 滑雪 - 洛谷
1.滑雪必须从高往下滑,所以不会有vis数组,因为不可能重新滑回来
2.当我们寻找一个最长路径的时候必须9->8->7->6是一个最长路径时,8的最长路径就已经确定了8->7->6
#include<iostream>
using namespace std;
//dfs遍历数组
int direction_x[]={-1,1,0,0};
int direction_y[]={0,0,-1,1};
int dp[107][107];
int map[107][107];
int r,c;
int res=-1;
int check(int x,int y){
if(x<=0||x>r||y<=0||y>c){
return 0;
}
return 1;
}
//返回i,j的最长路径
int dfs(int i,int j){
//如果当前搜索过
if(dp[i][j]!=0){
return dp[i][j];
}else{
//没搜索过 =1 开始搜索
dp[i][j]=1;
for(int k=0;k<4;k++){
int x=i+direction_x[k];
int y=j+direction_y[k];
if(check(x,y)&&map[x][y]<map[i][j]){
dp[i][j]=max(dp[i][j],dfs(x,y)+1);
}
}
}
return dp[i][j];
}
int main(){
cin>>r>>c;
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
cin>>map[i][j];
}
}
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
//保存所有节点的最长路径
res = max(res,dfs(i,j));
}
}
cout<<res;
return 0;
}
普通DFS
P1162 填涂颜色
换个思路找圈子内难,但是圈子外,加上一行用DFS可以全部遍历,通过visit判断是否走完
#include<iostream>
int n,matrix[37][37],visit[37][37];
int direction_x[] = {0,0,-1,1};;
int direction_y[]= {1,-1,0,0};
void dfs(int i,int j){
if(visit[i][j]==1||matrix[i][j]==1||i<0||i>n+1||j<0||j>n+1) return;
else{
visit[i][j]=1;
for(int k=0;k<4;k++){
dfs(i+direction_x[k],j+direction_y[k]);
}
}
}
int main(){
std::cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
std::cin>>matrix[i][j];
}
}
//找到第一个0
for(int i=0;i<=n+1;i++){
if(matrix[0][i]==0){
dfs(0,i);
break;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(matrix[i][j]==1){
std::cout<<matrix[i][j]<<" ";
}else{
if(visit[i][j]==0){
std::cout<<2<<" ";
}else{
std::cout<<0<<" ";
}
}
}
std::cout<<std::endl;
}
return 0;
}
P1706 全排列问题
#include<iostream>
#define maxsize 10005
#include<iomanip>
#include<vector>
using namespace std;
int n;
int visit[maxsize];
vector<int> arr;
void dfs(int i){
if(i>n){
for(int j=0;j<n;j++){
cout<<setw(5)<<arr[j];
}
cout<<endl;
}else{
for(int j=1;j<=n;j++){
//没有被选中
if(visit[j]==0){
visit[j]=1;
arr.push_back(j);
dfs(i+1);
arr.pop_back();
visit[j]=0;
}
}
}
}
int main(){
cin>>n;
dfs(1);
return 0;
}
P2089 烤鸡
1-3个数 然后全排列
#include<iostream>
#include<vector>
using namespace std;
int res=0;
int n;
int arr_res[50000][12];
vector<int> arr;
void dfs(int i){
if(i>=10){
int sum=0;
for(int j=0;j<arr.size();j++){
sum+=arr[j];
}
if(sum==n){
for(int j=0;j<arr.size();j++){
arr_res[res][j]=arr[j];
}
res++;
}
}else{
for(int j=1;j<=3;j++){
arr.push_back(j);
dfs(i+1);
arr.pop_back();
}
}
}
int main(){
cin>>n;
dfs(0);
cout<<res<<endl;
for(int i=0;i<res;i++){
for(int j=0;j<10;j++){
cout<<arr_res[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
P1219 [USACO1.5] 八皇后 Checker Challenge
第三次训练 - Virtual Judge[P1219 USACO1.5] 八皇后 Checker Challenge - 洛谷
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int n;
int res = 0;
int arr_res[20][20];
vector<int> arr;
bool check(int i,int j){
int x=0;
for(auto num: arr){
if(num==j){
return false;
}
if(abs(x-i)==abs(j-num)){
return false;
}
x++;
}
return true;
}
void dfs(int i){
if(i>=n){
//输出前三个解
if(res<3){
for(int j=0;j<n;j++){
arr_res[res][j] = arr[j];
}
}
res++;
}else{
for(int j=0;j<n;j++){
if(check(i,j)){
arr.push_back(j);
dfs(i+1);
arr.pop_back();
}
}
}
}
int main(){
cin>>n;
dfs(0);
for(int i=0;i<3;i++){
for(int j=0;j<n;j++){
//由于前面是从0开始的,所以这里要+1
cout<<arr_res[i][j]+1<<" ";
}
cout<<endl;
}
cout<<res;
return 0;
}
动态规划
P1059 [NOIP 2006 普及组] 明明的随机数(去重,排序想到set)
[P1059 NOIP 2006 普及组] 明明的随机数 - 洛谷
#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
vector<int> arr(1e6);
set<int> res;
int n;
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
int cnt=0;
for(int i=0;i<n;i++){
res.insert(arr[i]);
}
cout<<res.size()<<endl;
for(auto it : res){
cout<<it<<" ";
}
}
P1739 表达式括号匹配
#include<iostream>
#include<string>
using namespace std;
string s;
int main(){
cin>>s;
s.pop_back();
int top=-1;
char stack[1000000];
int cnt=0;
for(auto c : s){
//左括号进栈
if(c=='('){
stack[++top]=c;
}else if(c==')'){
//栈不能为空,并且必须是(
if(top==-1){
cout<<"NO";
return 0;
}else{
char tmp_c = stack[top--];
if(tmp_c!='('){
cout<<"NO";
return 0;
}
}
}
}
//栈为空
if(top==-1){
cout<<"YES";
}else{
cout<<"NO";
}
return 0;
}
U225269 01背包问题
#include<iostream>
#include<vector>
using namespace std;
vector<int> arr_v(1e6);
vector<int> arr_w(1e6);
int dp[5000][5000]={0},V,N;
int main(){
cin>>V>>N;
for(int i=1;i<=N;i++){
cin>>arr_v[i]>>arr_w[i];
}
for(int i=1;i<=N;i++){
for(int j=1;j<=V;j++){
if(arr_v[i]<=j){
dp[i][j] = max(dp[i-1][j],dp[i-1][j-arr_v[i]]+arr_w[i]);
}else{
dp[i][j]=dp[i-1][j];
}
}
}
cout<<dp[N][V];
}
P1049 [NOIP 2001 普及组] 装箱问题(01背包问题的变种)
[P1049 NOIP 2001 普及组] 装箱问题 - 洛谷
#include<iostream>
#include<vector>
using namespace std;
vector<int> arr_w(1e6);
int dp[31][20007]={0},V,N;
int main(){
cin>>V;
cin>>N;
for(int i=1;i<=N;i++){
cin>>arr_w[i];
}
for(int i=1;i<=N;i++){
for(int j=1;j<=V;j++){
if(arr_w[i]<=j){
dp[i][j] = max(dp[i-1][j],dp[i-1][j-arr_w[i]]+arr_w[i]);
}else{
dp[i][j]=dp[i-1][j];
}
}
}
cout<<V-dp[N][V];
}
P1115 最大子段和
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int n,dp[1000000];
vector<int> arr;
int main(){
cin>>n;
for(int i=0;i<n;i++){
int tmp;
cin>>tmp;
arr.push_back(tmp);
}
//初始化
dp[0]=arr[0];
for(int i=1;i<n;i++){
//当前值,或者前面值+1
dp[i] = max(arr[i],dp[i-1]+arr[i]);
}
int max = dp[0];
for(int i=1;i<n;i++){
if(dp[i]>max){
max = dp[i];
}
}
cout<<max;
return 0;
}
P1439 【模板】最长公共子序列
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int n,dp[100000][100000];
vector<int> arr_1(10007),arr_2(10007);
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr_1[i];
}
for(int i=1;i<=n;i++){
cin>>arr_2[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(arr_1[i]==arr_2[j]){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
}
int res = -1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
res = max(res,dp[i][j]);
}
}
cout<<res;
return 0;
}