算法笔记上机

算法笔记

nbuoj+洛谷基础算法题+其它

1224 哥德巴赫猜想(2)

题目描述
所谓哥德巴赫猜想,就是指任何一个大于2的偶数,都可以写成两个素数的和。现在输入一个偶数,要求寻找两个素数,使其和等于该偶数。由于可能有多组素数对满足条件,所以本题要求输出两数差最小的那两个素数。
注意 / 和% 的区别
以及函数调用求素数

#include<iostream>
using namespace std;
int issu(int a){
	int res=1;
	for(int i=2;i<a-1;i++){
		if(a%i==0){
			res=0;
			break;
		}
	}
	return res;
}
int main(){
	int n;
	cin>>n;
	int h=n/2;
	for(int i=h;i>1;i--){
		if(issu(i)&&issu(n-i)){
			cout<<i<<" "<<n-i<<endl;
			return 0;
		}
	}
}

1171 多个数的最小公倍数

__gcd(a,b)//最小公约数
lcm(a, b) = a * b / gcd(a, b);//最大公倍数

题目描述
也许你已经会了求2个数字最小公倍数的方法,但是如果求多个数字的最小公倍数,你又能找到办法吗?
使用set标记break节省时间

#include<iostream>
using namespace std;
int main(){
	int n;
	int a[101];
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=1;;i++){
		int set=1;//是 
		for(int j=0;j<n;j++){
			if(i%a[j]!=0){
				set=0;//不是 
				break;
			}
		}
		if(set==1){
			cout<<i<<endl;
			break;
		}
	}
}

1188 数字移位

题目描述
有n个整数,要求将前面各数字顺序向后移动m个位置,并将最后面的m个数变成最前面m个数。

#include<bits/stdc++.h>
using namespace std;
void reverse(int a[],int l,int r){
	int temp=0;
	int mid=(r-l+1)/2; //中间位置 
	for(int i=0;i<mid;i++){
		temp=a[i+l];
		a[i+l]=a[r-i];
		a[r-i]=temp;
	}
}
int main(){
	int n=0,m=0;
	int a[101];
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	reverse(a,0,n-1);
	reverse(a,0,m-1);
	reverse(a,m,n-1);
	for(int i=0;i<n-1;i++){
		cout<<a[i]<<" ";
	}
	cout<<a[n-1]<<endl;
}

1195 巧妙推算走楼梯(动态规划)

题目描述
有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
后面数据以前面为基础进行、使用相同算法

#include<iostream>
using namespace std;
int a[45]={0};

int main(){
	int n;
	int m;
	cin>>n;
	a[0]=0;
	a[1]=1;
	a[2]=1;
	a[3]=2;
	for(int i=4;i<42;i++){
		a[i]=a[i-1]+a[i-2];
	}
	for(int i=0;i<n;i++){
		cin>>m;
		cout<<a[m]<<endl;
	}
} 

P1090 合并果子(贪心)(STL栈)

在这里插入图片描述
STL优先队列

#include<iostream>
#include<queue>
using namespace std;
priority_queue< int,vector<int>,greater<int> >q;
//注意格式 !空格 pop出最小的那个
int main(){
	int n;
	int a;
	int sum=0;
	cin>>n;
	while(n--){
		cin>>a;
		q.push(a);
	}
	while(q.size()>=2){
		int a=q.top();
		q.pop();
		int b=q.top();
		q.pop();
		q.push(a+b);
		sum+=a+b;
	}
	cout<<sum;
}

自定义

#include<queue>
struct Node{
    int x,y;
    Node(int a=0, int b=0): x(a), y(b) {}
};
 
struct cmp{
    bool operator()(Node a, Node b){
        if(a.x == b.x)    return a.y>b.y;
        return a.x>b.x;
    }
};
    priority_queue<Node, vector<Node>, cmp>p;

P1219 八皇后(深搜+回溯)

在这里插入图片描述
注意for循环从1开始

n行n列

#include<iostream>
using namespace std;
int ans[14];//结果 
int check[3][28]={0};//列,左右斜线
int sum=0;
int n;
void eq(int line){
	if(line>n){//递归限制
		sum++; 
		if(sum>3)return;//只要3个
		else
		{
			for(int i=1;i<=n;i++)
				cout<<ans[i]<<" ";//输出结果
			cout<<endl;
			return;
		} 	
	}
	for(int i=1;i<=n;i++){//列遍历 有无  两斜线有无 
		if((!check[0][i])&&(!check[1][i+line])&&(!check[2][line-i+n])){
		//规律
			ans[line]=i;
			check[0][i]=1;check[1][i+line]=1;check[2][line-i+n]=1;
			eq(line+1);
			//回溯搜索下一行 
			//复原 
			check[0][i]=0;check[1][i+line]=0;check[2][line-i+n]=0;
		}
	}
} 
int main(){
	cin>>n;
	eq(1);//用行作为递归值
	cout<<sum;
	return 0;
}

P1443 马的遍历(搜索广度优先队列)

queue<A>q;
q.push(A{x1,y1,0});
#include<bits/stdc++.h>
#define re(i,a,b) for(int i=(a);i<=(b);i++) 
using namespace std;
struct A{
	int x,y,cnt;
};
int mp[401][401];
bool vis[401][401];
//int xx[]={1,1,-1,-1,2,2,-2,-2};
//int yy[]={2,-2,2,-2,1,-1,-1,1};
int xx[]={1,2,-1,-2,1,2,-1,-2};
int yy[]={2,1,2,1,-2,-1,-2,-1};
int main(){
	re(i,1,400)
	re(j,1,400)
	mp[i][j]=-1;
	int x1,y1,m,n;
	cin>>m>>n>>x1>>y1;
	queue<A>q;
	q.push(A{x1,y1,0});
	vis[x1][y1]=1;//存入即遍历到 
	mp[x1][y1]=0;
	while(!q.empty()){
		for(int i=0;i<8;i++){
			int dx=xx[i]+q.front().x;
			int dy=yy[i]+q.front().y;
			if(dx>=1&&dx<=m&&dy>=1&&dy<=n&&vis[dx][dy]==0){
				q.push(A{dx,dy,q.front().cnt+1});
				vis[dx][dy]=1;
				mp[dx][dy]=q.front().cnt+1;
			}
		}
		q.pop();//用完后出队列 
	}
	re(i,1,m){
		re(j,1,n){
			//cout<<mp[i][j]<<" ";	
			printf("%-5d",mp[i][j]); 
		}
		cout<<endl;
	}
	return 0;
}

P1259 黑白棋子的移动(递归 类似汉诺塔找规律)(难)

每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。

在这里插入图片描述

#include<iostream>
using namespace std;
int n,st,sp;// sp上次留下的空位置
char c[101];
void print()                                  //打印
{
	int i;
	cout<<"step "<<st<<':';
	for (i=1;i<=2*n+2;i++) cout<<c[i];
	cout<<endl;
	st++;
}
void init(int n)                             //初始化
{
	int i;
	st=0;
	sp=2*n+1;
	for (i=1;i<=n;i++) c[i]='o';
	for (i=n+1;i<=2*n;i++) c[i]='*';
	c[2*n+1]='-';c[2*n+2]='-';
	print();
}
void move(int k)                            //移动一步
{
	int j;
	for (j=0;j<=1;j++) 
	{
	   c[sp+j]=c[k+j];
	   c[k+j]='-';
	}
	sp=k;//上个空位 
	print();
}

void mv(int n)                                       //主要过程
{
	int i,k;
	if (n==4)                //n等于4的情况要特殊处理
	{
		move(4); move(8); move(2); move(7); move(1);
		}
	else
	{
		move(n); move(2*n-1); mv(n-1);
	}
}
int main()
{
	cin>>n;
	init(n);
	mv(n);
}

最后4步

在这里插入图片描述

P1969 积木大赛(实验7)

q求最小操作

#include <iostream>
using namespace std;
/*
5
2 3 4 1 2

5
*/
int main()
{
    int n,a,last=0,ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        if(a>last)ans+=(a-last);
        cout<<ans<<" "; 
        last=a;
        cout<<last<<endl;
    }
    cout<<ans<<endl;
}

P1318 积水面积(c++?)

img

#include<bits/stdc++.h>
//万能头大法好
using namespace std;
int main()
{
	int a[10001]={0},l[10001]={0},r[10001]={0},n,sum=0; //数组清零&定义n和答案
    //a用来储存原数据,l用来储存从左到右的最大值,r用来储存从右到左的最大值
	cin>>n;
	for(int i=1; i<=n; i++)
	{
		cin>>a[i]; //读入原数据
		l[i]=max(l[i-1],a[i]);
        //这里很重要!这是至i为止左边最高的高度
	}
	for(int i=n; i>=1; i--)
		r[i]=max(r[i+1],a[i]);
        //至i为止右边最高的高度
	for(int i=1; i<=n; i++)
	{
		if(min(l[i],r[i])-a[i]<0) sum+=0;
        //如果为负数,则说明当前的比较高,不可能积水,所以把0加上/或者不加0
		else sum+=min(l[i],r[i])-a[i];
        //因为只能积水到最低的高度处,所以用min。然后再减掉原来的高度,就可以等于i处砖块以上水的面积,如果是0的话也不用特判~
	}
	cout<<sum; //输出一下答案
	return 0;
}

P1048 采药(实验8 )🧡

01背包问题
在这里插入图片描述

for(int j = t;j >=c;j--){
	dp[j] = max(dp[j-c]+v,dp[j]);
}
#include<bits/stdc++.h>
using namespace std;
int m,t;
int dp[1005];
int c;//时间
int v;//价值
int main(){
	cin>>t>>m;
	for(int i=1;i<=m;i++){//物品序号 
		cin>>c>>v;//和上一个物品没有关联 
		for(int j=t;j>=c;j--){//时间 
			dp[j]=max(dp[j-c]+v,dp[j]);
			//倒退 有这个或没有
		}
	}
	cout<<dp[t];
	return 0;
} 

差分
(对区间数组加同时减,降低算法复杂度)
类似(#444. 铺地毯 沐风oj)
在这里插入图片描述

#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e6+7;
ll a[N];//原数组 
ll b[N];//差分数组 
ll s[N];//差分数组的前缀和 
ll res[N];//对原数组进行m次操作后的结果 
/*
5 1
9 1 2 5 3
2 4 1

O(n) 
s 0 1 1 1  0 0
b 0 1 0 0 -1 0
*/
int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
	
	while (m--) {
		ll x, y, z;
		scanf("%lld%lld%lld", &x, &y, &z);
		b[x] += z;
		b[y+1] -= z;//抵消,之后没有 
	}
	for (int i = 1; i <= n; ++i) s[i] = s[i-1] + b[i];
	for (int i = 1; i <= n; ++i) res[i] = a[i] + s[i];
	for (int i = 1; i <= n; ++i) cout << res[i] << " ";
	return 0;
}

王道上机书

1暴力

枚举
反序数+注意初试化

#include<iostream>
using namespace std;
int rev(int x){
	int re=0;//注意初始化为0!!! 
	while(x!=0){
		re*=10;
		re += x%10;
		x/=10;
	}
	return re;
}

int main(){
	for(int i =1000;i<=9999;i++){
		if(i*9 == rev(i)){
			cout<<i<<endl;
		}
	}
}

模拟
画图:模拟数组
寻找规律啊
题目:Hello World for U#

n2随长度增加呈现出一个有规律的数列,3个一组
从最短长度5开始,n2为:3,4,3,4,5,4,5,6,5,6,7,6,7,8,7,8,9,8,9,10......
int suren2(int len){//计算n2
    if(len%3==0||len%3==2) return len/3+2;
    else return len/3+1;
}

日期问题

#include<iostream>
using namespace std;
//日期问题 
int year,month,day;
int ans=0;
int daytab[2][13]={
	{0,31,28,31,30,31,30,31,31,30,31,30,31},
	{0,31,29,31,30,31,30,31,31,30,31,30,31}
};
bool isLeapyear(int year){//4 并且 100  或400 
	return (year%4==0&&year%100==0)||(year%400==0);
} 
int main(){
	while(scanf("%d%d%d",&year,&month,&day) != EOF){
	//循环输入!!!
		for(int i=1;i<month;i++){
			ans+=daytab[isLeapyear(year)][i]; 
		}
			ans+=day;
			cout<<ans;
	}
}

其它模拟
区间除树问题:最后可以不用遍历,当为1变false,数量–;
手机键盘:注意建立模拟记录数组,keytable【】

输入
scanf
%c 读入一个字符
%d 读入十进制整数
%s 读入一个字符串,遇空格、制表符或换行符结束。
输出
yyyy-mm-dd形式可能有0格式凑0
printf("%04d-%02d-%02d\n",year,month,day);

2二分查找

KY199 查找

#include<iostream>
#include<algorithm>
using namespace std;
int n, m;
const int MAXN = 1000;
int a[MAXN];
bool BinarySearch(int target, int n) {
    int l = 0;
    int r = n;
    while (l <= r) {
        int middle = (l + r) / 2;
        if (a[middle] < target) {
            l =  middle + 1;
        } else if (a[middle] > target) {
            r = middle - 1;
        } else {
            return true;
        }
    }
    return false;
}
int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a, a + n);
    cin >> m; //查找个数
    for (int i = 0; i < m; i++) {
        int t;
        cin >> t;
        if (BinarySearch(t, n)) {
            cout << "YES" << endl;
        } else cout << "NO" << endl;
    }
    return 0;
}
/*
4
9 8 17 6
*/

3字符串相关知识

string s = "How are you?";
s.erase(s.begin(),s.begin()+4);//are you?
t.erase(index,num);

string s1 = s.insert(0, "How "); //How do you

string s = "What's your name?";
s.replace(0, 2, "tt");//ttat’s your name? 
//replace起始位置,个数,替换字符串的值

s.find()//返回查找位置未找到返回string::npos
if(t.find("ewq")==string::npos){
		cout<<"nofind";//未查找到为string::nops
}
	
cout<<t.substr(1,3);//截取字符串(开始,个数)

string str;
getline(cin,str);
cout<<str;//getline可以不考虑空格

//反转
reverse(s.begin(),s.end());

//'a''z'相差25
cout<<'A'-'a'; //-32

str[i] = (str[i]-'A'-5+26)%26+'A';
//加减循环算法,+26%26可以抵消不用分情况

KY127 统计字符(字符存储)

#include <iostream>
#include <algorithm>
using namespace std;
string str1,str2;
int number[128];
int main()
{
	while(getline(cin,str1)){
		if(str1=="#"){
			break;
		}
		getline(cin,str2);
		for(int i=0;i<128;i++)number[i]=0;//注意清0 
		for(int i=0;i<str2.length();i++){
				number[str2[i]]++;			
		}
		for(int i=0;i<str1.length();i++){
			cout<<str1[i]<<" "<<number[str1[i]]<<endl;
		}
	}
}
/*
I
THIS IS A TEST
i ng
this is a long test string
#

I 2
i 3
  5
n 2
g 2

*/ 

4贪心

01背包
部分包
购买贺年卡(注意不需要时候break)
硬币问题(从最大循环一次,int t = min(a[i],sum/v[i]); 全部或者可以买的)
删数问题(使用字符处理,每次删除后删除递增最后一个数 最后删除最后一个数 s.erase(0,1);)

拦截导弹问题添加链接描述(最长递增递减子序列 不要忘记初值设置为1)
排队接水(最小的先接水,可以先举例子,ans+=num[i-1].T*(n-i))
均分纸牌(用绝对值思想,初始化为平均值的差值)

if(num[i]!=0){ 		
	sum++;//次数+1
	num[i+1]+=num[i];//更新移动后后一堆纸牌数
}

senior‘s gun (模拟)

	for(int i=0;i<n;i++){
		if((i>=m)&&gun[i]>=monstor[i]){
			//还有怪物射杀并且可以杀死怪物 
			break; 
		}
		ans+=(gun[i]-monstor[i]);
	}

KY4 代理服务器(未完成)

区间贪心🧡
每次选择结束时间最早的,让后面空余时间最多

#include<iostream>
#include<algorithm>
using namespace std;
struct node{
	int l,r;
}a[105]; 
bool camp(node a, node b){
	return a.r<b.r;
}
int n;
int ans=1;//注意题意 
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i].l>>a[i].r;
	}
	sort(a,a+n,camp);
	int temp = a[0].r;//最早结束时间
	for(int i=1;i<n;i++){
		if(a[i].l>=temp){//开始时间>=结束时间 
			ans++;
			temp=a[i].r;
		} 
	}
	cout<<ans<<endl;
}
/*
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
*/

KY155 To Fill or Not to Fill(代码量较多学思想)
贪心,每次选油价最低的,然后对路程进行覆盖
注意细节!

if(fill == 1)
if(fill = 1 )
#include<iostream>
#include<algorithm>
/*
测试用例 
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
50 1300 12 2
7.10 0
7.00 600

输出结果 
749.17
The maximum travel distance = 1200.00
*/
using namespace std;
struct Station{
	double price;
	int distance;
}; 

bool camp(Station a, Station b){
	return a.price<b.price;
}

int main(){
	int cmax,d,davg,n; //最大容量,行驶距离, 每单位油可行驶距离,站数量 
	while(cin>>cmax>>d>>davg>>n){
		Station station[n];
		bool flag[d+1];//标记是否走过
		for(int i=1;i<=d;i++)flag[i]=0; 
		for(int i=0;i<n;i++){
			cin>>station[i].price>>station[i].distance; 
		} 
		sort(station,station+n,camp);
		double currentprice = 0;
		for(int i=0;i<n;i++){
			int currentdistance=0;//此站台加油后行驶的距离 
			for(int j=station[i].distance+1;j<=cmax*davg+station[i].distance;j++){
				if(flag[j]==false){
					flag[j]=true;
					currentdistance++;
				}
				//行驶完成或油用完
				if(j==d||j==station[i].distance+cmax * davg){
					currentprice += station[i].price*currentdistance/(davg*1.0); 
					break;
				} 
			}
		}
		int fill = 1;//是否走完 
		double journey=0;
		for(int i=1;i<=d;i++){
			if(flag[i]==true)journey++; 
			else {
				fill  = 0;
				break;
			}
		}
		if(fill==1){
			printf("%.2f-完成\n",currentprice);
		}else{
			printf("%.2f-未完成\n",journey);
		}
	}	
}

5递归与分治

汉诺塔
假设从一个状态到另一个状态要f(n),总结出f(n)和f(n-1)表达式,同时有最终结果值

#include<iostream>
using namespace std;
/*
1
3
12
*/
long long f(int x){
	if(x==1){
		return 2;
	}else {
		return 3*f(x-1)+2;
	}
}
int main(){
	int n;
	while(~scanf("%d",&n) ){
		cout<<f(n)<<endl;
	}
	return 0;
} 

铺瓷砖(递归)
用1和2组成n可能排列

#include<bits/stdc++.h>
using namespace std;
/*
4
5
*/ 
int sum;
int n; 
void f(int x){
	if(x==n){
		sum++;
	}
	if(a>n){//加二的情况过了
	 return;
	}
	f(x+1);
	f(x+2);
}
int main(){
	cin>>n;
	f(0);
	cout<<sum;
	return 0; 
} 

树节点分治

在这里插入图片描述

#include<iostream>
using namespace std;
/*
3 12
0 0

4
*/
int  f(int m,int n){
	if(m>n){
		return 0;
	}else{
		return 1+f(m*2,n)+f(m*2+1,n);
	}
}
int main(){
	int m,n;//根  节点  从根到节点有多少个 
	while(scanf("%d %d",&m,&n) !=EOF){
		cout<<f(m,n)<<endl;
	}
	return 0;
} 

6动态规划

最大连续子列和
pri

dp[i]=max(dp[i-1]+a[i],a[i]);
//dp含义:以a[i]结尾的最大子列和

最长递减子序列并不是连续的

dp[i]以a[i]结尾的最大递减子序列

	for(int i=0;i<n;i++){
		dp[i] = 1;//初始化为1 
		for(int j=0;j<i;j++){
			if(a[j]>=a[i]){
				dp[i] = max(dp[j]+1,dp[i]);
			}
		}
		ans = max(dp[i],ans);
	}

最长公共子序列

状态转移方程为:

当s1[i] = s2[j]时: dp[i][j] = dp[i-1][j-1]+1;
当s1[i] != s2[j]时: dp[i][j] = max(dp[i-1][j],dp[i][j-1]); 
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
/*
abcd
cxbydz
2
*/
const int maxn = 1001;
string s1;
string s2;

int main(){
	while(cin>>s1>>s2){
		int n = s1.length();
		int m = s2.length();
		int dp[n+1][m+1];
		memset(dp,0,sizeof(dp));
		//dp[i+1][j+1]  
		//以s1[i]为结尾和以s2[j]为结尾村存在的最长公共子序列 
		int ans =0;
		for(int i=1;i<=n;i++){//从一开始用于防止i-1约为
			for(int j=1;j<=m;j++){
				if(s1[i-1] == s2[j-1]){
					//dp向后移动一个位置防止i-1越界 
					dp[i][j] = dp[i-1][j-1]+1;
				}else{
					dp[i][j] = max(dp[i-1][j],dp[i][j-1]); 
				} 
			}
		}
		cout<<dp[n][m]<<endl;
	}
	
} 

最长回文串

在这里插入图片描述

#include<iostream>
#include<cstring>
const int maxn = 1010;
char S[maxn];
int dp[maxn][maxn];

int main()
{
    gets(s);
    int len = strlen(S), ans = 1;
    memset(dp, 0, sizeof(dp));   //dp数组初始化
    //边界
    for(int i = 0; i<len; i++)
    {
        dp[i][i] = 1;     
        if(i < len - 1)
        {
            if(S[i] == S[i+1])
            {
                dp[i][i + 1] = 1;
                ans = 2;    //初始化时注意当前最长回文子串长度
            }
        }
    }
    //状态转移方程
    for(int L = 3; L<=len; L++)
    {
        for(int i = 0; i + L - 1<len; i++)
        {
            int j = i + L - 1;
            if(S[i] == S[j]&&dp[i + 1][j - 1] == 1)
            {
                dp[i][j] = 1;
                ans = L;     //更新最长回文子串长度
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

合并石头(区间)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
//#define int long long
using namespace std;
const int maxn=1e6+5;
int dp[1005][1005],sum[maxn],a[maxn];
int main(){
    memset(dp,0x3f3f3f3f,sizeof(dp));
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
        dp[i][i]=0;
    }
    for(int len=2;len<=n;len++){
        for(int i=1;i+len-1<=n;i++){
            int j=i+len-1;
            for(int k=i;k<=j;k++){
                dp[i][j]=
                min(dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1],dp[i][j]);
            }
        }
    }
    cout<<dp[1][n]<<endl;
}

背包问题
01背包模板

for(int i=0;i<n;i++){
	cin>>p>>v;//价格 价值 
	for(int j=c;j>=p;j--){ 
		dp[j] = max(dp[j-p]+v,dp[j]);
	}
}
c是可以出卖的资源如金钱或者背包容量
p是获得物品i要付出的代价同上
v是获得物品i获得的利益
#include<iostream>
#include<cstring>
using namespace std;
int c,n;
int ans = 0; 
int main(){
	while(cin>>c>>n){
		int p;//价格 
		int v;//价值 
		int dp[c+1];	
		memset(dp,0,sizeof(dp)); 
		for(int i=0;i<n;i++){
			cin>>p>>v;//价格 价值 
			for(int j=c;j>=p;j--){ 
				dp[j] = max(dp[j-p]+v,dp[j]);
			}
		}
		cout<<dp[c];
	} 
 
}

饥饿的牛(hunger)(选择不重复区间得到最大)

dp[j] = max(dp[j],dp[s[i].x - 1] + s[i].total)
 #include<bits/stdc++.h>
#include<map>
using namespace std;
//this is a book
struct node{
	int x,y,total;
};
const int maxn = 2005;
int dp[maxn];
bool cmp(node a,node b){
	return a.y<b.y; //按照最后一位从小到大排序 
}
int main()
{
	int n;
	cin>>n;
	node a[n];
	int x,y;
	for(int i=0;i<n;i++){
		cin>>a[i].x>>a[i].y;
		a[i].total=a[i].y-a[i].x+1;
	}
	sort(a,a+n,cmp);
	for(int i=0;i<n;i++){
		for(int j = a[n-1].y;j>=a[i].y;j--){
			dp[j] = max(dp[j],dp[a[i].x-1]+a[i].total);
		}
	}
	cout<<dp[a[n-1].y];
	return 0;
 } 
 

矩阵连乘(计算最小值)(思考)
在这里插入图片描述

KY14 最小邮票数
求最小,初始值为最大

if(j==v)dp[j]=1;//初值 
else dp[j] = min(dp[j-v]+1,dp[j]);
#include<iostream>
#include<cstring>
/*
10
5
1 3 3 3 4

3
*/
using namespace std;
const int INF = 0x3ffffff;
int c,n;
int main(){
	int v;//价值 
	cin>>c>>n;	
	int dp[c+1];
	for(int i=0;i<=c+1;i++){
		dp[i]=INF;
	} 
	for(int i=0;i<n;i++){
		cin>>v;//价值 
		for(int j=c;j>=v;j--){
			if(j==v){
				dp[j]=1;//初值 
			}
			else dp[j] = min(dp[j-v]+1,dp[j]);
		}
	}

	if(dp[c]!=INF){
		cout<<dp[c];
	}else	
		cout<<0;	
}

完全背包(每个物品有无穷数量)
和01相同,不过顺序计算

for(int j=p;j<=c;j++)dp[j] = min(dp[j-p]+v,dp[j]);

多重背包
多一层循环
优化 …2^c

#include<iostream>
#include<cstring>
using namespace std;
int v[510],w[510],s[510],dp[6100];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>v[i]>>w[i]>>s[i];
	for(int i=1;i<=n;i++){
		for(int j=m;j>=1;--j){
			for(int k=0;k<=s[i]&&j>=k*v[i];k++){
				//第j个物品 拿k个 
				dp[j] = max(dp[j],dp[j-k*v[i]]+k*w[i]);
			}
		}
	} 
	cout<<dp[m]; 
 
}

7.1数组栈队列

vector 数组

	for(int i = 0;i<a.size();i++)cout<<a[i];//输出
	for(vector<int>::iterator it = a.begin();it!=a.end();it++)cout<<*it;//输出
	vector<int>::iterator it = a.begin()+1;
	a.insert(it,4);//出入 4数组下标
	a.erase(a.begin()+1);//删除 

queue push pop front() empty

stack push pop top empty() size

在这里插入图片描述

#include<iostream>
#include<queue>
using namespace std;
/*
8 3 4
1 2 3 4 5 6 7 8
*/
int n,p,m;//小孩  开始 间隔
queue<int>a;
int main()
{
	cin>>n>>p>>m;
	for(int i=1;i<=n;i++){
	 	a.push(i);
	}
	for(int i=1;i<p;i++){
		a.push(a.front());
		a.pop();
	}
	int num = n;
	int i=0;
	while(num){
		int cnt = m-1;
		while(cnt--){
			a.push(a.front());
			a.pop();
		}
		//出队
		cout<<a.front();
		a.pop();
		num--;
	}
}

在这里插入图片描述

//第一个数字为所有事件
//第一个元素为1,代表进入收容所,第二个元素为动物的编号,正数代表狗,负数代表猫
//第一个元素为2,代表收养,第二个元素为0,代表所有与动物的先后,第二个数字为1,代表收养狗,若为-1
//代表是收养猫 。 不合法的直接忽略 , 输出动物的的编号 , 以空格间隔;
#include<cstdio>
#include<queue>
using namespace std;
struct Animals{
    int num;//编号
    int seq;//序号
};
int main(){
    int seq = 0;
    int n;//问题的规模
    scanf("%d",&n);
    queue<Animals> dogQue;
    queue<Animals> catQue;
    for(int i = 0 ; i < n ; ++ i ){
        int x , y;
        scanf("%d%d",&x,&y);
        if(1 == x){//动物进入收容所
 
            if( y > 0){
                Animals dog;
                dog.num = y;
                dog.seq = seq ;
                ++seq;
                dogQue.push(dog);
            }
            else{
                Animals cat;
                cat.num = y;
                cat.seq = seq ;
                ++seq;
                catQue.push(cat);
 
            }
        }
        else{//动物出收容所
            if( 0 == y ){//所有动物先后
                if(catQue.empty() && dogQue.empty()){//猫狗都空 忽略
                    continue;
                }
                else if (catQue.empty() && !dogQue.empty()
                || !dogQue.empty() && !catQue.empty() && dogQue.front().seq < catQue.front().seq){
                    //所有动物先后 ,零养狗的情况 1.猫空 狗不空 2.猫狗都不空但是 狗的seq<猫的seq
                    printf("%d ",dogQue.front().num);
                    dogQue.pop();
                }
                else{
                    printf("%d ",catQue.front().num);
                    catQue.pop();
                }
            }
            else if(1 == y){//领养狗
                if(dogQue.empty()){
                    continue;
                }
                else{
                    printf("%d ",dogQue.front().num);
                    dogQue.pop();
                }
            }
            else{//领养猫
                if(catQue.empty()){
                    continue;
                }
                else{
                    printf("%d ",catQue.front().num);
                    catQue.pop();
                }
            }
        }
    }
 
}

在这里插入图片描述

//括号匹配
#include<iostream>
#include<stack>
using namespace std;
/*
)(rttyy())sss)(
*/
int main()
{
	stack<int>a;	
	string t;
	cin>>t;
	for(int i=0;i<t.length();i++){
		//cout<<t;
		if(t[i]>='a'&&t[i]<='z'){
			t[i]=' ';
		}
	}
	
	
	for(int i=0;i<t.length();i++){
		if(t[i]=='('){
			a.push(i);
		}
		if(t[i]==')'){
		
			if(a.empty()){
				t[i]='?';	
			}
			if(!a.empty()){//符合 
				t[a.top()]=' ';
				t[i]=' ';
				a.pop();
			}
			//cout<<t;
		}
	//cout<<t;
	}
	while(!a.empty()){
		t[a.top()]='$';
		a.pop();
	}
	cout<<t;
}

7.2数据结构(排序树、搜索树)

KY212 二叉树遍历
在这里插入图片描述

#include<iostream>
#include<stack>
using namespace std;
/*
)(rttyy()sss)(
*/
void treeprint(string a,string b){
	if(a.size()!=0){
		int r = b.find(a[0]);//头所在中序位置 
		treeprint(a.substr(1,r),b.substr(0,r));//左 
		treeprint(a.substr(r+1),b.substr(r+1));//右 
		cout<<a[0];
	} 
}
int main()
{	
	string a,b;
	//a 头左     右
	//b 左     头右 
	//          r 
	//输出 左右头 
	while(cin>>a>>b){
		treeprint(a,b);
	} 
	return 0;
}

先序遍历->中序遍历

使用数组

#include<iostream>
#include<stack>
using namespace std;
/*
abc##de#g##f###
c b e g d f a 
先序遍历->中序遍历 
*/
const int N1=1e8+5;
const int N2=1e2+5;
int pos;
char tree[N1];
char str[N1];
void create(int pos){//创建树 
	char c = str[t++];
	if(c=='#'){
		return;
	}
	tree[pos]=c;//赋值	
	create(2*pos);//更换位置 
	create(2*pos+1);
}
void traverse(int root){
	if(tree[root]==0){
		return;
	} 
	traverse(2*root);
	cout<<tree[root]<<" ";
	traverse(2*root+1);
} 
int main()
{	
	while(cin>>str){
		pos=0;
		create(1);
		traverse(1);
		cout<<endl;
	}
}

KY207 二叉排序树
在这里插入图片描述

//Binary Search Tree
#include<iostream>
#include<cstdio>
using namespace std;
struct TreeNode{
    int data;
    TreeNode* leftChild;
    TreeNode* rightChild;
    TreeNode(int x): data(x),leftChild(NULL),rightChild(NULL){}
};
TreeNode* Insert(TreeNode* root,int x,int father){
    if(root==NULL){
        root = new TreeNode(x);
        cout<<father<<endl;
    }
    else if(x<root->data){
        root->leftChild = Insert(root->leftChild,x,root->data);
    }
    else if(x>root->data){
        root->rightChild = Insert(root->rightChild,x,root->data);
    }
    return root;
}
int main(){
    int N;
    int temp;
    TreeNode* root = NULL;
    cin>>N;
    for(int i=0; i<N; i++){
        cin>>temp;
        root = Insert(root,temp,-1);
    }
    return 0;
}

KY223 二叉搜索树

在这里插入图片描述

#include <iostream>
#include <queue>
using namespace std;

//二叉排序树二
struct TreeNode{
    int  data;
    TreeNode *leftchild;
    TreeNode *rightchild;
    TreeNode(int x):data(x),leftchild(NULL),rightchild(NULL){}

};

void visit(TreeNode *t){
    cout<<t->data<<" ";
}

void PreOrder(TreeNode *root){
    if(root==NULL)return;
    visit(root);
    PreOrder(root->leftchild);
    PreOrder(root->rightchild);
}

void InOrder(TreeNode *root){
    if(root==NULL)return;
    InOrder(root->leftchild);
    visit(root);
    InOrder(root->rightchild);
    return;
}

void PostOrder(TreeNode *root){
    if(root==NULL)return;
    PostOrder(root->leftchild);
    PostOrder(root->rightchild);
    visit(root);
    return;
}


TreeNode* Insert(TreeNode *root,int x){
    if(root==NULL){
        root=new TreeNode(x);
    }
    if(x==root->data);
    else if (x<root->data)root->leftchild=Insert(root->leftchild,x);
    else root->rightchild=Insert(root->rightchild,x);
    return root;
}

int main(){
    int n;
    while(cin>>n){
        TreeNode *root=NULL;
        while(n--){
            int x;
            cin>>x;
            root=Insert(root,x);
        }
        PreOrder(root);
        printf("\n");
        InOrder(root);
        printf("\n");
        PostOrder(root);
        printf("\n");
    }
    return 0;
}

KY124 二叉搜索树

描述

判断两序列是否为同一二叉搜索树序列

输入:

2
567432
543267
576342
0

输出:

YES
NO
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
struct node
{
    char val;
    node *lchild, *rchild;
    node(int v):val(v), lchild(NULL), rchild(NULL){}
};
bool flag;
node *insert(node *root, int x) //依次插入每个值
{
    if (root == NULL) //节点为空时,插入此节点
    {
        root = new node(x);
        return root;
    }
    if (root->val > x)                         //如果这个值小于左儿子
        root->lchild = insert(root->lchild, x); //递归向下寻找相应的位置,回溯赋值,构建链表
    else                                        //同理
        root->rchild = insert(root->rchild, x);
    return root;
}
void check(node *root, node *judge) //传入标准树和判断树的地址
{
    if (root != NULL && judge != NULL) //如果两个地址都不为空,即此节点两棵树都有值,只需判断值是否相同
    {
        if (root->val != judge->val)      //判断此节点的值是否和标准树一致
            flag = false;
        check(root->lchild, judge->lchild); //前序遍历
        check(root->rchild, judge->rchild);
    }
    else if (root != NULL || judge != NULL) //如果两颗树中,只有一棵树在这个节点有值,那么这两棵树肯定不一致
        flag = false;
}
int main()
{
    int n;
    while (cin>>n)
    {
        node *root = NULL; //标准树地址为空
        string s;
        cin >> s;
        for (int i = 0, len = s.length(); i < len; i++) //构建一颗标准树
            root = insert(root, s[i]);
        for (int i = 0; i < n; i++) //n组数据
        {
            flag = true;       //标记
            node *judge = NULL; //判断树地址为空
            cin >> s;
            for (int i = 0, len = s.length(); i < len; i++) //构建判断树
                judge = insert(judge, s[i]);
            check(root, judge); //中序遍历,检查两棵树是否一致
            if (flag)
                printf("YES\n");
            else
                printf("NO\n");
        }
    }
}

7.3树形结构(priority_queue< int >q、map、set)

priority_queue< int >q   push  
top
int main(){
	int a[] = {2,1,2,3,4,7}; 
	priority_queue<int>b;
	for(int i=0;i<6;i++){
		b.push(a[i]);
	}
	while(b.empty()==false){
		cout<<b.top();
		b.pop();
	}
}

底层默认大根堆,可以修改为小根堆

priority_queue<int>q;
==priority_queue<int,vector<int>,less<int> >q;

priority_queue<int,vector<int>,greater<int> >q;
//greater<int> 表示数字小的优先级越大。 



结构体
// f1使用friend其排序与sort排序刚好相反 
struct node
{
	string name;
	int price;
	//friend bool operator<(const node &f1,const node &f2) 
	//建议使用上面的引用来提高效率 
	friend bool operator<(node f1,node f2)
	{
		return f1.price<f2.price;
	}
};
priority_queue<node> q;
// f2不使用 friend 友元将它写在外面 

friend bool operator<(node f1,node f2)
{
		return f1.price<f2.price;
}

map

查找学生信息(麻烦了)

#include<iostream>
#include<map>
using namespace std;
int main(){
    int n, m;
    cin >> n;
    map<string, string> students;
    for(int i = 0; i < n; i ++){
        string id, name, gender, age;
        cin >> id >> name >> gender >> age;
        students[id] = id + " " + name + " " + gender + " " + age;
    }
    cin >> m;
    string target;
    for(int i = 0; i < m; i ++){
        cin >> target;
        if(students.find(target) != students.end())
        //if(students[target]!="")
            cout<< students[target] << endl;
        else cout<<"No Answer!"<<endl;
    }
    return 0;
}

KY146 魔咒词典

#include<iostream>
#include<cstdio>
#include<string>
#include<map>
using namespace std;
int main(){
    int d,l;
    string s;
    map<string,string> mp;
    while(getline(cin,s)){
        if(s=="@END@") break;
        d=s.find("]");//定位指定字符的位置,为了将字符串分割
        l=s.length();
        string m=s.substr(0,d+1);//利用substr提取相关字符串
        string n=s.substr(d+2,l);
        mp[m]=n;//将分开的两段字符串分别映射成键和值
        mp[n]=m;
    }
    int n;
    scanf("%d",&n);
    getchar();
    string t;
    while(n--&&getline(cin,s)){
            if(mp[s]==""){//如果没有找到相关的映射
                cout<<"what?"<<endl;
            }else{
               t=mp[s];
               if(t.find("[")!=-1){//如果找到的字符串里含有指定字符,就利用substr去除,为-1时未找到
                    cout<<t.substr(1,(t.length()-2))<<endl;
                }else{//如果没有就直接输出
                    cout<<t<<endl;
                }
            }
    }
    return 0;
}

set容器(去重排序)
set<int> q;     //以int型为例 默认按键值升序
set<int,greater<int>> p;  //降序排列 
int x;
q.insert(x);	//将x插入q中
q.erase(x);		//删除q中的x元素,返回0或1,0表示set中不存在x
q.clear();		//清空q
q.empty();		//判断q是否为空,若是返回1,否则返回0
q.size();		//返回q中元素的个数
q.find(x);		//在q中查找x,返回x的迭代器,若x不存在,则返回指向q尾部的迭代器即 q.end()
第k小数
#include<bits/stdc++.h>
using namespace std;
int main()
{
    set <int> s; 
	int n,k; 
	cin>>n>>k; 
	int a;
    for(int i=0;i<n;i++) 
	{
		cin>>a;
	    s.insert(a);
	} 
 
    if(k>=s.size()) 
	{
	    cout<<"NO RESULT"; 
	    return 0;
	}  
    set<int>::iterator it;
    it=s.find(k);
	cout<<*it;
	
	return 0; 
}

8图论(并查集、最小生成树、最短路径)

KY175 连通图

使用并查集

Init() 初始化 find()找到父节点 Union()合并集合

#include<cstdio>
using namespace std;
#define N 1000
int father[N];//存储了父亲的下标
int high[N];//存储了某个根的树的高度
void Init(int n){
    //最开始每个元素单独构建一个集合,每个集合是一棵树
    for (int i = 1; i <= n; ++i) {
        //i的编号
        father[i]=i;//每个结点都是树的根
        high[i]=1;
    }

}
int find(int x){
    if (x!=father[x]){
        //find的路径压缩,找到祖先以后先不返回,而是设为自己的新父亲。
        father[x]= find(father[x]);
    }
    //x就是树的根
    return father[x];
}
void Union(int x, int y, int &num){

        x= find(x);
        y= find(y);
    if (x!=y){
        //x y原本不属于同一个连同子图
        --num;
    }
    if (high[x]<high[y]){// y更深
        father[x]=y;
    } else if (high[x]>high[y]){
        father[y]=x;
    } else{  // 一样深度
        father[y] = x;
        ++high[x];
    }
}
int main(){
        int n;
        int m;
    while (scanf("%d%d",&n,&m)!=EOF){
        if (m==0&&n==0){
            break;
        }
        Init(n);
        int num=n;//连通子图的数量
        for (int i = 0; i < m; ++i) {
            int x,y;
            scanf("%d%d",&x,&y);
            Union(x,y,num);
        }
        if (num==1){
            printf("YES\n");
        } else{
            printf("NO\n");
        }
    }

}

Kruskal 算法(最小生成树)

KY148 还是畅通工程

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std; 

const int MAXN = 1000;

struct Edge{    //定义边结构体
	int from;
	int to;
	int length;
};

Edge edge[MAXN * MAXN];   //边的数量是定点数量的平方

int father[MAXN];    //用以表示每个节点的父节点是什么样的

int height[MAXN];   

void Initial(int n){    //n个节点
	for(int i = 0; i < n; ++i){    //初始状态下,每个节点的父节点是其自身
		father[i] = i;
		height[i] = 0;
	}
	return;
}

int Find(int x){
	if(x != father[x]){  //表示当前节点不是根节点,需要继续向上查找
		father[x] = Find(father[x]);    //将路径压缩,可以提高查找效率
	}
	return father[x];
}

void Union(int x,int y){  //合并,将一棵树作为另一棵树的子树
	x = Find(x);   //找到x的根节点
	y = Find(y);    //找到y的根节点
	if(x != y){    //说明这两个节点本身不属于同一个集合,需合并
		if(height[x] < height[y]){   //将树高较高的作为树高较低的子树进行合并
			father[x] = y;    
		}else if(height[x] > height[y]){
			father[y] = x;    
		}else{   //高度相同时,可任意连接
			father[y] = x;   
			height[x]++;   //树的高度递增1
		}
	}
}

bool Compare(Edge x,Edge y){
	return x.length < y.length;
}

int Kruskal(int n,int edgeNum){
	Initial(n);   //先初始化
	sort(edge,edge + edgeNum,Compare);  //按照边的权值升序排序
	int sum = 0;   //统计路径之和
	for(int i = 0; i < edgeNum; ++i){
		Edge current = edge[i];
		if(Find(current.from) != Find(current.to)){
		//两个定点不属于同一个集合,就进行合并
			Union(current.from,current.to);
			sum += current.length;
		}
	}
	return sum;
}



int main(){
	int n;
	while(scanf("%d",&n) != EOF){
		if(n == 0){
			break;
		}
		int edgeNum = n * (n - 1) / 2;   //n个顶点,n * (n - 1) / 2条边
		for(int i = 0; i < edgeNum; ++i){    //输入边的信息
			scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].length);
		}
		int answer = Kruskal(n,edgeNum);
		printf("%d\n",answer);
	}
	return 0;
}

dijkstra算法的实现单元最短路径

KY107

畅通工程续

已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

9深搜广搜

bfs模板
const int dx ={...}//建立方向矩阵 
int bfs(node st) {
	q.push(st);//初始化压入 d = 0; 
	while (!q.empty()) {//非空 
		node now = q.front();
		q.pop();//获取头建立temp 然后出栈 
		vis[]=1//标记已访问
		for (int i = 0; i < 6; i ++) {//方向遍历 
			int x = t.x + dx[i], y = t.y + dy[i]//相加 
			if (...) continue;//不符合边界条件或者访问过 
			d = d + 1;//若有求路程+1 
			if (..) return ..;//结束条件 
			vis[]=1//标记已访问 
			// q.push({x,y,z});
			node stt;
			stt.x = x, stt.y = y, stt.z = z;
			q.push(st);//压入 
		}
	}
	return 0;
}
int main() {
	bfs();
	return 0;
}

dfs模板

void dfs(int r,int num){//需要约束的变量 
    if(..) return ;//约束条件 返回 
    for(int i = 0;i < n;i ++){
        if(..){//满足条件 
            vis[i] = 1;//标记已经遍历 
            dfs(r+1,num+1);//搜下一个 
            vis[i] = 0;//需要复原 
        }
    }
    dfs(r+1,num);//其它情况 
}
int main()
{
    dfs(0,0);
}
994. 腐烂的橘子(BFS)
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
    int cnt =0;
    int time=0;
    int dx[4]={-1, 1, 0, 0};
    int dy[4]= {0, 0, -1, 1};
    int n = grid.size();
      int m = grid[0].size();
      queue<pair<int,int>>q;
      for(int i=0;i<n;i++){
          for(int j=0;j<m;j++){
              //把所有烂橘子扔进队列🧡
              if(grid[i][j]==2){
                q.push({i,j});
              }
              if(grid[i][j]==1){
                  //新鲜橘子总数
                  cnt++;
                  //把所有新鲜橘子标记为为访问状态
                  grid[i][j]=-1;
              }
             
          }
      }

      while(!q.empty()){
          //判断当前是否有新的烂橘子产生
          bool flag =false;
          //当前队列大小
          int curSize =q.size();
          //循环当前队列中的元素
          for(int i=0;i<curSize;i++){
            int x=q.front().first;
            int y=q.front().second;
            q.pop();
            //遍历周边橘子
           for(int i=0;i<4;i++){
             int newX = x+dx[i];
              int newY =y+dy[i];
               if(newX>=0&&newX<n &&newY>=0&&newY<m&&grid[newX][newY]==-1){
                   //把新鲜橘子变坏
                   grid[newX][newY]=2;
                   //表示当前有烂橘子产生
                   flag =true;
                   //同时新鲜橘子个数减少
                   cnt--;
                   //把新的烂橘子加入到队列当中去
                   q.push({newX,newY});
               }
           }
            
          }
          //在本轮循环中如果有烂橘子产生,那么时间点就加1
           if(flag) time++;

      }
      //最后 如果还有新鲜橘子,则说明不可能存在所有的那远哥的新鲜橘子都会烂,否则就返回最小分钟数time
      return cnt ? -1 : time;
    }
};

swer);
	}
	return 0;
}

dijkstra算法的实现单元最短路径

KY107

畅通工程续

已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

9深搜广搜

994. 腐烂的橘子(BFS)
#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
    int cnt =0;
    int time=0;
    int dx[4]={-1, 1, 0, 0};
    int dy[4]= {0, 0, -1, 1};
    int n = grid.size();
      int m = grid[0].size();
      queue<pair<int,int>>q;
      for(int i=0;i<n;i++){
          for(int j=0;j<m;j++){
              //把所有烂橘子扔进队列🧡
              if(grid[i][j]==2){
                q.push({i,j});
              }
              if(grid[i][j]==1){
                  //新鲜橘子总数
                  cnt++;
                  //把所有新鲜橘子标记为为访问状态
                  grid[i][j]=-1;
              }
             
          }
      }

      while(!q.empty()){
          //判断当前是否有新的烂橘子产生
          bool flag =false;
          //当前队列大小
          int curSize =q.size();
          //循环当前队列中的元素
          for(int i=0;i<curSize;i++){
            int x=q.front().first;
            int y=q.front().second;
            q.pop();
            //遍历周边橘子
           for(int i=0;i<4;i++){
             int newX = x+dx[i];
              int newY =y+dy[i];
               if(newX>=0&&newX<n &&newY>=0&&newY<m&&grid[newX][newY]==-1){
                   //把新鲜橘子变坏
                   grid[newX][newY]=2;
                   //表示当前有烂橘子产生
                   flag =true;
                   //同时新鲜橘子个数减少
                   cnt--;
                   //把新的烂橘子加入到队列当中去
                   q.push({newX,newY});
               }
           }
            
          }
          //在本轮循环中如果有烂橘子产生,那么时间点就加1
           if(flag) time++;

      }
      //最后 如果还有新鲜橘子,则说明不可能存在所有的那远哥的新鲜橘子都会烂,否则就返回最小分钟数time
      return cnt ? -1 : time;
    }
};
``


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值