• 递推+模拟---想好如何存储?


    递推+模拟

    输入输出问题

    CCF-CSP考试历年真题题型分类

    CCF-CSP考试历年真题题型分类

    分组输入——可能有多组测试数据,对于每组数据

    当你加上这个时,只要你不输入 ^Z(ctrl+z) , 条件为真,就会一直循环下去,只有你输入 ^Z,条件为假,终止循环。
    BC100 直角三角形图案

    #include
    using namespace std; 
    int main()
    {
    	int n = 0;
    	while (cin>>n)//大家在分组输入时直接用起来呀!
    	{
    		for (int i = 0; i < n; i++)
    		{		for (int a = 0; a <= i; a++)
    				printf("* ");
    				printf("\n");		           
    		}
    	}
    	return 0;
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    递推—从前面已知态—>后续未知态

    AcWing 3777. 砖块

    AcWing 3777. 砖块

    题目大意:求翻转相邻的两个砖块能否是所有颜色都相同!!
    
    思路:递推!强调递推只是一种思路,没有模板!!!
    
    砖块翻转2次以上都是重复的,因此只需要判断它翻转1次还是0次!!问题就简化成为判断此时的砖块需不需要翻转!!
    我们假设所有砖块最后都能翻转成B,从1—n-1,进行比较判断第i个颜色是否与B相同,不同则翻转i与i+1个,依次判断完全后会发现1–n-1都翻转成为了B,此时第n个无法翻转,只需判断第n个颜色即可!
    
    同理,假设最后都能翻转成W,如果两种假设都不能实现,则样例无法满足!!!
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    #include
    using namespace std;
    int n;
    void update(char &c)//翻转第i个字符 
    {
    	if(c=='W')	c='B';
    	else	c='W';
     } 
    bool check(string s,char c)
    {
    	vector<int> v;//存储是---第i次操作 
    	for(int i=0;i<n-1;i++)//存储在[0,n-1]----翻转[0,n-2] 
    	{
    		if(s[i]!=c)//如果不是想要的字符----就翻转 
    		{
    			update(s[i]);
    			update(s[i+1]);
    			v.push_back(i);//记录下翻转了第[i,i+1]个砖块 
    		}
    	}
    	if(s[n-1]!=s[0])	return false;//---翻转过程结束后,若最后一个字符与其他字符不一致 
    	cout<<v.size()<<endl;//翻转操作的次数 
    	for(auto x:v) cout<<x+1<<" ";//+1的原因---下标的原因 
    	if(v.size())	cout<<endl;//若是---没有翻转过---则比翻转过少一个换行 
    	return true; 
    }
    int main()
    {
    	int T;
    	cin>>T;
    	while(T--)
    	{
    		cin>>n;
    		string s;
    		cin>>s;
    		if(!check(s,'W')&&!check(s,'B'))//这段代码&&前面不满足后面就不再执行,因此方便了代码书写!
    			cout<<-1<<endl; 
    	}
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    AcWing 1208. 翻硬币

    AcWing 1208. 翻硬币

    在这里插入图片描述
    如果通过每次翻转两枚相邻硬币,能从状态一变为状态二,则两个状态之间必定有偶数个不同状态的硬币。

    模拟法:

    从最左侧开始遍历,如果该位置硬币状态与目标不同,就翻动该位置和该位置后面的两枚硬币。

    因为题目说了有解,所以遍历到倒数第二枚的时候,所有硬币状态就与目标相同了。

    这个方法也有点贪心的思路,每次追求当前位置状态与目标状态一致。我还是喜欢称它为模拟法。

    #include
    using namespace std;
    string st,ed;
    int ans;
    void update(char &c)//翻转第i个字符 
    {
    	if(c=='o')	c='*';
    	else	c='o';
    }
    int solve()
    {
    	for(int i=0;i<st.size()-1;i++)//遍历[0,n-1]的字符 
    	{
    		if(st[i]!=ed[i]) 
    		{
    			update(ed[i]);//同时翻转[i,i+1]两枚硬币 
    			update(ed[i+1]);
    			ans++;//返回的答案 
    		}
    	}
    	return ans;
    }
    int main()
    {
    	cin>>st;
    	cin>>ed;
    	cout<<solve()<<endl;
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    AcWing 1211. 蚂蚁感冒

    AcWing 1211. 蚂蚁感冒
    AcWing 1211. 蚂蚁感冒—讲解

    
    #include
    using namespace std;
    const int N=50+10;
    
    int a[N];
    
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=0;i<n;i++)	cin>>a[i];
    	int l=0;//感冒蚂蚁的右边---向左走 
    	int r=0;//感冒蚂蚁的左边---向右走 
    	for(int i=1;i<n;i++)
    	{
    		if(abs(a[0])<abs(a[i]) && a[i]<0)
    			l++;
    		if(abs(a[0])>abs(a[i]) && a[i]>0)
    			r++; 
    	}
    	if(a[0]>0)//当感冒蚂蚁---向右走 
    	{
    		if(l!=0)
    			cout<<l+r+1<<endl;
    		else		//特殊情况 
    			cout<<1<<endl;
    	}
    	else//当感冒蚂蚁---向左走 
    	{
    		if(r!=0)
    			cout<<l+r+1<<endl;
    		else		//特殊情况 
    			cout<<1<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    AcWing 3433. 吃糖果

    AcWing 3433. 吃糖果

    #include
    using namespace std;
    
    const int N = 22;
    int dp[N];
    int main()
    {
        int n;
        cin >> n;
        dp[0]=dp[1]=1;
        for(int i=2;i<=n;i++)
            dp[i]=dp[i-1]+dp[i-2];
        cout<<dp[n]<<endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    AcWing 821. 跳台阶

    AcWing 821. 跳台阶

    #include
    using namespace std;
    
    const int N = 22;
    int dp[N];
    int main()
    {
        int n;
        cin >> n;
        dp[1]=1;
        dp[2]=2;
        for(int i=3;i<=n;i++)
            dp[i]=dp[i-1]+dp[i-2];
        cout<<dp[n]<<endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    模拟

    202212-2-csp-训练计划

    请添加图片描述

    #include
    using namespace std;
    const int N=110;
    
    int rely[N];//记录i的依赖----i依赖于rely[i] 
    int t[N];//每个科目的训练需要时间 
    
    int early[N];
    int late[N];
     
     
    int main()
    {
    	int n,m;
    	
    	cin>>n>>m;
    	for(int i=1;i<=m;i++)
    		cin>>rely[i];//存储i的依赖是rely[i] 
    	for(int i=1;i<=m;i++)
    		cin>>t[i];
    		
    		
    	//正向计算---最早开始时间	
    	for(int i=1;i<=m;i++)
    	{	
    		if(!rely[i])//如果不依赖别的科目=1 
    			early[i]=1;
    		else		//如果依赖别的科目=别的科目最早开始时间+别的科目的训练时间 
    			early[i]=early[rely[i]]+t[rely[i]]; 
    		cout<<early[i]<<" ";
    	 }
    	cout<<endl;
    	
    	
    	
    	//计算最晚开始时间---倒着计算 
    	bool success=true;//标记---每一个最晚时间是否合法 
    	for(int i=m;i>=1;i--)
    	{
    		late[i]=n-t[i]+1;//i不被后面的科目所依赖时
    		
    		for(int j=i;j<=m;j++)//找到后面的j---在依赖i 
    		{
    			if(rely[j]==i)//i被后面的i所依赖---可能有多个依赖于i的
    				late[i]=min(late[i],late[j]-t[i]);//最晚时间要尽可能的早些 		
    		 } 
    		if(late[i]<1)//最晚时间不合法时 
    			success=false; 
    	 }
    	 if(success)//当每一个科目都满足要求时
    	 {
    	 	for(int i=1;i<=m;i++)
    	 		cout<<late[i]<<" ";
    	  } 
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    202206-2-csp-寻宝!大冒险!—稀疏矩阵—数学坐标系

    AcWing 4510. 寻宝!大冒险!

    对应+匹配+不越界

    用pair存储绿化图中非零坐标,二维数组存储藏宝图坐标
    遍历pair,分别以pair中的点作为藏宝图左下角的点
     边缘判断:
     绿化图和藏宝图上1的数量必须对应,当两者个数相等时进行判断
    对应+匹配+不越界
    
    题目超时的原因在于存储大地图的稀疏矩阵太大,遍历比较耗时长。
    本解法利用局部地图减少了遍历的范围。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    #include
    using namespace std;
    const int N= 1e3+10,M=55;
    typedef pair<int,int> PII;
    #define x first
    #define y second
    int b[M][M];
    PII tree[N];
    
    int main()
    {
    	int n,L,S;//树的棵数、绿化图和藏宝图的大小 
    	cin>>n>>L>>S;
    	for(int i=0;i<n;i++) cin>>tree[i].x>>tree[i].y;
    	
    	int tc=0;//记录藏宝图上树的个数 
    	for(int i=S;i>=0;i--)//---注意坐标系的读入 
    		for(int j=0;j<=S;j++)
    		{
    			cin>>b[i][j];
    			tc+=b[i][j]; 
    		}
    			
    	int ans=0;//统计答案的个数 
    	for(int i=0;i<n;i++)
    	{
    		int sx=tree[i].x;
    		int sy=tree[i].y;
    		if(sx+S>L||sy+S>L)//如果地图上越界 ---经典的错误,标准的零分 
    			continue;
    		int cnt=0;//记录地图相应区域上---树的个数 
    		bool flag=true;//是否相匹配 
    		for(int j=0;j<n;j++)
    		{
    			int x=tree[j].x;
    			int y=tree[j].y;
    			if(x>=sx && x<=sx+S && y>=sy && y<=sy+S)//在区域内 
    				if(!b[0+x-sx][0+y-sy])//地图上是树的位置---藏宝图上不是树时 
    				{
    					flag=false;//直接不匹配---返回 
    					break;//不需要再判断下去了 
    				}
    				else
    					cnt++;
    		 } 
    		 if(cnt==tc && flag)//个数相同---并且---匹配成功 
    			ans++;
    	}
    	cout<<ans<<endl;
    	return 0;
     } 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    202112-2-csp-序列查询新解—数学问题

    AcWing 4281. 序列查询新解

    请添加图片描述

    请添加图片描述

    #include
    using namespace std;
    const int N=1e5+10;
    typedef long long LL;
    int n,m;
    int a[N];
    LL R;
    LL get(int l,int r)  // 求g[l] + g[l + 1] + ... + g[r]
    {
        if (l/R==r/R)//如果仅有一小段时 
    		return (LL)(r-l+1)*(l/R);
    		
        //g(x)有多段时 
        int a=l/R+1,b=r/R-1;
        LL res=(a+b)*(LL)(b-a+1)/2*R;  // 中间部分
        res+=(a-1)*(LL)(a*R-l);  // 左边界
        res+=(b+1)*(LL)(r-(b*R+R)+1);  // 右边界
        return res;
    }
    
    int main()
    {
        cin>>n>>m;
        for (int i=1;i<=n;i++) cin>>a[i];
        a[n+1]=m;
        R=m/(n+1);
    
        LL res=0;
        for (int i=0;i<=n;i++)
        {
            int l=a[i];//[l,r]在该区间上a[i]的取值相同 
    		int r=a[i+1]-1;
            int x=l/R;//[l,r]区间对应的g(x)的取值 
    		int y=r/R;
            if (y<=i || x>=i)//若 g(x)每一小段都在a[i]--[l,r]区间的下方---或上方 
            {
                res+=abs((LL)i*(r-l+1)-get(l,r));//|f(x)-g(x)| 
            }
            else//有交集时 
            {
                int mid=i*R;//交点的最左边 ---i=mid/R 
                res+=abs((LL)i*(mid-l+1)-get(l,mid));  // 左半边        |f(x)-g(x)| 
                res+=abs((LL)i*(r-mid)-get(mid+1,r));  // 右半边        |f(x)-g(x)| 
            }
        }
        cout<<res<<endl;//输出误差 
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    202009-2-csp-风险人群筛查

    AcWing 3293. 风险人群筛查

    阅读理解:“连续 k 个或更多坐标均位于矩形内(含边界)”是说明last>=k,并不是有>k个不同点位于高危区域内

    #include
    using namespace std;
    const int N=1e3+10;
    int n;//居民数 
    int k;//连续k个坐标 
    int t;//每个居民共t个坐标
    
    int res;//经过人数
    int ans;//逗留人数 
    int main()
    {
    	int x1,y1,x2,y2;//矩形框的坐标 
    	cin>>n>>k>>t>>x1>>y1>>x2>>y2;
    	
    	while(n--)
    	{
    		bool pass=false;
    		bool wait=false;
    		int s=0;//记录连续停留时间 
    		for(int i=0;i<t;i++)
    		{
    			int x,y;
    			cin>>x>>y;
    			if(x>=x1 && x<=x2 && y>=y1 && y<=y2)//处在高危地区
    			{
    				s++;
    				pass=true;
    				if(s>=k)
    					wait=true;
    			 }
    			 else
    			 	s=0;	 		
    		}
    		if(pass)
    			res++;
    		if(wait)
    			ans++; 
    			
    	}
    	cout<<res<<endl<<ans<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    201912-2-csp-回收站选址

    AcWing 3283. 回收站选址

    #include
    using namespace std;
    const int N =1E3+10;
    typedef pair<int,int> PII;
    #define x first
    #define y second
    PII q[N];
    int n;
    //左上-上-右上-右-右下-下-左下-左 
    int dx[8]={-1,-1,-1,0,1,1, 1, 0};
    int dy[8]={-1, 0, 1,1,1,0,-1,-1};
    int ans[5];//返回答案
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;i++)
    		cin>>q[i].x>>q[i].y;
    		
    	for(int i=0;i<n;i++)
    	{
    		int s[8]={0};//存储第i个点的八个方向上---点的信息
    		for(int j=0;j<n;j++)
    		{
    			for(int k=0;k<8;k++)
    			{
    				int a=q[i].x+dx[k];
    				int b=q[i].y+dy[k];
    				if(a==q[j].x && b==q[j].y)//如果某方向上有垃圾
    					s[k]++;
    			}
    		}
    		if(s[1] && s[3] && s[5] && s[7])//满足--上下左右都有垃圾
    			ans[s[0]+s[2]+s[4]+s[6]]++;
    	}
    	for(int i=0;i<5;i++)
    		cout<<ans[i]<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    201909-2-csp-小明种苹果(续)

    AcWing 3278. 小明种苹果(续)

    在这里插入图片描述

    //(剩余数量)a=(总数-摘数)b-掉数 
    #include
    
    using namespace std;
    const int N=1e3+10;
    bool st[N];//判断第i棵树是否出现掉落情况 
    vector<int> q[N]; //存储第i棵苹果树的操作
    
    int T = 0;//T---蔬果后苹果剩余总数
    int D = 0;//D---出现掉落的苹果树总数 
    int E = 0;//E---连续三颗树发生掉落的组数  
    
    int get(vector<int> a,int b)
    {
    	int res=a[b];
    	for(int i=b+1;i<a.size();i++)
    	{
    		if(a[i]<0)
    			res+=a[i];
    	}
    	return res;
    }
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=0;i<n;i++)
    	{
    		int k;
    		cin>>k;
    		for(int j=0;j<k;j++)//存储一棵树的信息 
    		{
    			int x;
    			cin>>x;
    			q[i].push_back(x);//将对应的操作存储下来 
    		}
    		
    		
    		
    		
    		
    		//(剩余数量)a=(总数-摘数)b-掉数 
    		int a;//a---某棵苹果树---剩余数量 
    		int b;//b---某棵苹果树---从开始总数---一次次梳果---=(总数-摘数)
    		for(int j=q[i].size()-1;j>=0;j--)
    		{
    			if(q[i][j]>0)
    			{
    				a=get(q[i],j);//从第j个操作开始计算剩余苹果数
    				break; 
    			}
    		}
    		T+=a;
    		
    		
    		
    		
    		b=get(q[i],0);//从第0个操作开始计算---一次次梳果---=(总数-摘数)
    		if(b>a)
    		{
    			st[i]=true;
    			D++;
    		 } 	
    	}
    	
    	
    	
    	for(int i=0;i<n;i++)//环状---分组 
    	{
    		if(st[i] && st[(i+1)%n] && st[(i+2)%n])
    			E++;
    	}
    	cout<<T<<" "<<D<<" "<<E<<endl;
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    201812-2-csp-小明放学

    AcWing 3268. 小明放学
    在这里插入图片描述

    出现的问题
    1 long long 
    2 表达式 x<y<z →x<y && y<z
    
    
    思路:
    
    1.此题需要判断当小明到达红绿灯时,此时红绿灯的颜色情况,以及剩余的时间。
    
    2.判断红绿灯的情况需要根据循环来判断,即采用总时间%(红+绿+黄),得到的余数用来判断。
    
    3.绿灯情况可以直接走,不用计时,则在判断红绿灯颜色时,为简化代码,可不用写绿灯的情况,另外k=0的情况可以直接计时。
    
    4.为避免内存不够,数据类型都采用long long类型。
    
    细节注意:
    
    1.刚开始知道的时间为出发时刻的时间
    
    2.红绿灯的变化顺序为:红->绿->3.黄灯等待完后需要等待红灯
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    #include
    using namespace std;
    typedef long long LL;
    LL ans;
    
    int main()
    {
    	int r, y, g;
    	cin>>r>>y>>g;	//输入红-黄-绿灯的时间 
    	int n;
    	cin>>n;
    	while(n--)
    	{
    		int op,t;	//输入操作--时间 
    		int pos;	//定义红绿灯在r+y+g数轴上的位置 
    		cin>>op>>t;
    		if(op==0)	//不需要等待---经过一段道路 
    			ans+=t;
    		else		//如果是路口---判断红绿灯 
    		{
    			if(op==1)	//出发时刻时---红灯 
    				pos=r-t; 
    			if(op==2)	//出发时刻时---黄灯 
    				pos=r+y+g-t;
    			if(op==3)		//出发时刻时---绿灯 
    				pos=r+g-t;
    				
    				
    			t=(ans+pos)%(r+g+y);	// 从出发---到达红绿灯在数轴上的位置 
    			if(t<r)		//当到达路口时---是红灯 
    				ans+=r-t;
    			if(t>=r+g)	//当到达路口时---是黄灯 
    				ans+=r+g+y-t+r;	
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    201809-2 -csp-买菜

    AcWing 3263. 买菜

    1.此题主要看小H和小W两个人的时间段重合的长度。
    
    2.设置一个数组作为时间轴,若小H和小W 的买菜时间与坐标轴重合,则对应的点的值加1。
    
    3.易知,当一个坐标点对应的值为2时,表示小H和小W的时间重合,此时两人可以聊天。
    
    4.统计该数组中有多少个值为2的点,就可以得到两人聊天的总时间。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    #include
    using namespace std;
    const int N=1e6+10;
    int n;
    int a[N];
    int ans;
    int main()
    {
    	cin>>n;
    	int x,y;
    	for(int i=0;i<n;i++)
    	{
    		cin>>x>>y;
    		for(int j=x;j<y;j++)
    		{
    			a[j]++;
    		}
    	}
    	for(int i=0;i<n;i++)
    	{
    		cin>>x>>y;
    		for(int j=x;j<y;j++)
    		{
    			a[j]++;
    		}
    	}
    	for(int i=0;i<N;i++)
    	{
    		if(a[i]==2)
    			ans++;
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    在这里插入图片描述

    #include
    using namespace std;
    typedef pair<int,int> PII;
    #define x first
    #define y second
    const int N=2e3+10;
    PII a[N];
    PII b[N];
    long long ans;
    int get(PII p,PII q)
    {
    	if(p.y<q.x || p.x>q.y)
    		return 0;
    	else
    		return min(p.y,q.y)-max(p.x,q.x);
    }
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=0;i<n;i++)
    	{
    		int l,r;
    		cin>>l>>r;
    		a[i]={l,r};
    	}
    	for(int i=0;i<n;i++)
    	{
    		int l,r;
    		cin>>l>>r;
    		b[i]={l,r};	
    	}
    	
    	
    	for(int i=0;i<n;i++)//暴力遍历每个区间---每个区间---判断两个区间的交集 
    	{
    		for(int j=0;j<n;j++)
    		{
    			ans+=get(a[i],b[j]);//get函数---回去两个区间的交集 
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    201703-2-csp-学生排队

    AcWing 3243. 学生排队

    1. 用一维数组的下标代表排队的位置,一维数组对应的值为学生的学号;
    
    2. 定义一个find函数,利用find函数找到p同学对应的位置;
    
    3. 若q>0,则先将a同学后的b位同学向前移动一个单位,由于是顺序整体移动,则直接采用后一个同学位置覆盖前一个同学的位置的方法,即a[i-1]=a[i],最后再移动p同学的位置。
    
    4. 若q<0,则先将p同学前的q位同学向后移动一个单位,由于是顺序整体移动,则直接采用前一个同学位置覆盖后一个同学的位置的方法,即a[i+1]=a[i],最后再移动p同学的位置。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    #include
    using namespace std;
    
    const int N=1e3+10;
    int q[N];
    int main()
    {
    	int n,m;
    	cin>>n;
    	for(int i=1;i<=n;i++) q[i]=i; 
    	cin>>m;
    	while(m--)
    	{
    		int a,b;
    		int k;
    		cin>>a>>b;
    		for(int i=1;i<=n;i++)//找到a同学在数组中的新下标
    			if(q[i]==a)
    				k=i;
    		if(b>0)
    		{
    			for(int i=0;i<b;i++)
    				swap(q[k+i],q[k+i+1]);//向后交换---一共交换b次 
    		}
    		else
    		{
    			b=-b;
    			for(int i=0;i<b;i++)
    				swap(q[k-i],q[k-i-1]);//向前交换---一共交换b次 
    		}
    	}
    	for(int i=1;i<=n;i++)
    		cout<<q[i]<<" ";
    	cout<<endl; 
    	
    	
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    201612-2 -csp-工资计算

    AcWing 3238. 工资计算
    在这里插入图片描述

    #include
    using namespace std;
    
    
    int a[]={	  0,  1500, 4500,  9000, 35000, 55000, 80000, 1000000};//纳税区间 
    double b[]={0, 0.03,  0.1,  0.2,  0.25,   0.3,  0.35,  0.45};//某纳税区间的纳税率	
    
    int T;	
    
    
    int get(int x)
    {
        if (x<=3500) //不需要纳税 
    		return x;
        else
        {
            double tax=0;		//缴纳的税钱 
            x-=3500;		//纳税所得额 
            for (int i=1;i<=7;i++)
                if (x>=a[i-1])
                tax+=(min(x, a[i])-a[i-1])*b[i];
        return x+3500-tax;
        }
    }
    
    int main()
    {
        cin >> T;
    
        int l=T, r=T*2;//税前工资最多是税后工资的2倍 
    	//直接利用二分查找,找到符合条件的实际工资 
        while (l<r){
            int mid=(l+r)>>1;
            if(get(mid)>=T)//得到的税后工资>=T 
    			 r=mid;
            else
    			 l=mid+1;
        }
        cout<<r<<endl;
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    201609-3-csp-炉石传说

    AcWing 3234. 炉石传说

    #include
    using namespace std;
    struct Role{			//存储英雄及随从的信息 
    	int a;//攻击力
    	int h;//血量 
    }q[2][10]; //第一位是英雄信息----其余七位是该英雄的随从信息 
    
    
    void remove(int k,int pos)//第pos位置上的随从死亡---右边的随从占据他的位置 ---把死亡的随从放到最边上
    {
    	for(int i=pos;i<=7;i++)
    		swap(q[k][i],q[k][i+1]);
    
    }
    int main()
    {
    	int n;
    	cin>>n;
    	int k=0;//表示到谁的回合了 ---0-先手---1-后手 
    	
    	q[0][0].h=q[1][0].h=30;//两名英雄的血量初始化 
    	while(n--)
    	{
    		string op;//操作类型 
    		cin>>op;
    		if(op=="end")	//到下一位英雄回合 
    			k^=1;
    		else if(op=="summon")	//安排随从上场 
    		{
    			int pos,a,h;
    			cin>>pos>>a>>h;
    			for(int i=7;i>pos;i--)
    				q[k][i]=q[k][i-1];		//将原来pos位置及右边的随从---右移
    			q[k][pos]={a,h};		//pos位置放置新随从 
    		}
    		else
    		{
    			int a,d;		//a:本方攻击者位置,对方被攻击者位置
    			cin>>a>>d;
    			q[k][a].h-=q[!k][d].a;		//本方掉血 
    			q[!k][d].h-=q[k][a].a;		//对方掉血
    			if(a && q[k][a].h<=0)	
    				remove(k,a);		//我方随从死亡
    			if(d && q[!k][d].h<=0) 
    				remove(!k,d);		//对方随从死亡 
    		}
    			
    	}
    	//结局如何--- 
    	if(q[0][0].h<=0)		//我方死亡 
    		cout<<-1<<endl;
    	else if(q[1][0].h<=0)		//对方死亡 
    		cout<<1<<endl;
    	else		//平局 
    		cout<<0<<endl;
    		
    		
    	//局面上的英雄和随从情况
    	for(int k=0;k<2;k++)
    	{
    		cout<<q[k][0].h<<endl;
    		int s=0;		//统计活着的随从数量
    		for(int i=1;i<=7;i++)
    			if(q[k][i].h>0)
    				s++;
    		cout<<s<<" ";		
    		for(int i=1;i<=s;i++)
    			cout<<q[k][i].h<<" ";
    		cout<<endl; 
    	}	
    	 
    	 
    	 return 0;
    	
     } 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    201609-2-csp-火车购票

    AcWing 3233. 火车购票

    两种情况分类讨论
    1有连续的位置
    2没有连续的位置--用来此次分配
    
    • 1
    • 2
    • 3
    #include
    using namespace std;
    
    bool st[20][5];//表示位置是否被使用了 
    
    int main()
    {
    	int n;
    	cin>>n;
    	while(n--)
    	{
    		int p;		//购票指令 
    		cin>>p;
    		bool success=false;			//针对于该购票指令是否连续分配成功 
    		for(int i=0;i<20;i++)
    		{
    			for(int j=0;j<5;j++)		//某行的五个位置 
    			{
    				int s=0;		//某行-某个位置开始--可以连续分配的位置数量
    				for(int k=j;k<5;k++)
    				{
    					if(!st[i][k])
    						s++;
    					else
    						break;
    	
    				 }
    				if(s>=p)		//够分配的 
    				{
    					for(int k=0;k<p;k++)		//从第j个位置起---分配p个位置 
    					{
    						st[i][j+k]=true;
    						cout<<i*5+(j+1)+k<<" ";
    					}
    					success=true;		//连续分配成功 
    					break;
    				 } 
    			}
    			if (success) 
    				break;
    		}
    		
    		if(!success)
    			for(int i=0;i<20;i++)
    				for(int j=0;j<5;j++)
    					if(!st[i][j])		//从小到大离散的找p个位置 
    					{
    						p--;
    						st[i][j]=true;
    						cout<<5*i+(j+1)<<" ";
    					}		
    		
    	cout<<endl;	
    	}
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    201604-2-csp-俄罗斯方块(利用下一个时刻判断+补充最后一层满格)

    AcWing 3228. 俄罗斯方块

    判断是否能够放进
    这里采取了比较巧妙的做法 
    即当前状态如果刚好有重叠 那么它的上一个状态i-1 肯定没重叠也就是我们要找的答案
    
    • 1
    • 2
    • 3
    #include 
    using namespace std;
    const int N = 20;
    
    int g[N][N];//原来的画布 
    int s[N][N];//用于判断重叠的画布 
    int p[4][4];
    
    bool draw(int x, int y)
    {
        memcpy(s, g, sizeof(s));//复制画布 
        for (int i = 0; i < 4; i ++ )
            for (int j = 0; j < 4; j ++ )
                if (p[i][j])//如果是方块 
                {
                    int a = x + i, b = y + j;//方块向下移动---X步  
                    s[a][b] ++ ;
                    if (s[a][b] == 2) return true;//如果重叠---返回 
                }
        return false;
    }
    
    int main()
    {
        for (int i = 0; i < 15; i ++ )
            for (int j = 0; j < 10; j ++ )
                cin >> g[i][j];
        //给俄罗斯图最后一行添加砖块--用于判断特殊情况 
        for (int i = 0; i < 10; i ++ ) g[15][i] = 1;
    	
    
        for (int i = 0; i < 4; i ++ )
            for (int j = 0; j < 4; j ++ )
                cin >> p[i][j];
    
        int c;//板块最左边开始的地方 
        cin >> c;
        c -- ;
    
        for (int i = 0; ; i ++ )
            if (draw(i, c))//---i时刻重叠 
            {
                draw(i - 1, c);//---说明i-1时刻是最终位置 
                break;
            }
            
    	//输出方块停止时刻的样子 
        for (int i = 0; i < 15; i ++ )
        {
            for (int j = 0; j < 10; j ++ )
                cout << s[i][j] << ' ';
            cout << endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    201512-2-csp消除类游戏

    AcWing 3223. 消除类游戏

    #include 
    using namespace std;
    const int N = 33;
    
    int n, m;
    int g[N][N];
    bool st[N][N];//每个点的状态---是否被删除 
    
    int main()
    {
        cin >> n >> m;
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ )
                cin >> g[i][j];
    
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ )
            {
                int l = j, r = j, u = i, d = i, x = g[i][j];
                while (l >= 0 && g[i][l] == x) l -- ; //向左走 
                while (r < m && g[i][r] == x) r ++ ;	//向右走 
                while (u >= 0 && g[u][j] == x) u -- ;	//向上走 
                while (d < n && g[d][j] == x) d ++ ;	//向下走 
                st[i][j] = r - l - 1 >= 3 || d - u - 1 >= 3;	//如果某个方向上>=3---被删掉 
            }
    
        for (int i = 0; i < n; i ++ )
        {
            for (int j = 0; j < m; j ++ )
                if (st[i][j]) cout << 0 << ' ';
                else cout << g[i][j] << ' ';
            cout << endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    201312-3-csp-最大的矩形

    201312-3最大的矩形

    #include
    using namespace std;
    const int N=1e3+10; 
    int n;
    int a[N];
    int ans;
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i];
    	for(int i=1;i<=n;i++)//枚举一下每一个位置---作为矩形的高度 
    	{
    		int l=i,r=i;
    		while(l>=1&&a[l]>=a[i])	l--;//往左边开始枚举 ---左边界 
    		while(r<=n&&a[r]>=a[i])	r++;//往右边开始枚举 ---右边界
    		
    		ans=max(ans,a[i]*(r-l-1));//更新矩阵的高*宽
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    201412-3-csp-集合竞价

    AcWing 3209. 集合竞价
    AcWing 3209. 集合竞价讲解

    #include
    using namespace std;
    const int N=5000+10;
    typedef long long LL;
    struct node{
    	int type;//0---买    1---卖
    	double p;//价格
    	LL s;//股数
    	bool is_del; 
    }q[N];
    
    int n;
    int main()
    {
    	string str;
    	while(cin>>str)
    	{
    		if(str=="buy")
    		{
    			double p;
    			int s;
    			cin>>p>>s;
    			q[++n]={0,p,s};
    		}
    		if(str=="sell")
    		{
    			double p;
    			int s;
    			cin>>p>>s;
    			q[++n]={1,p,s};
    		}
    		if(str=="cancel")
    		{
    			int id;
    			cin>>id;
    			q[id].is_del=true;
    			q[++n].is_del=true;
    		}
    	}
    	LL max_s=0;//最大开盘价---最大的成交量
    	double max_price=0;
    	for(int i=1;i<=n;i++)
    		if(!q[i].is_del)
    		{
    			double temp_price=q[i].p;
    			LL sum1=0;//买入的总股数 
    			LL sum2=0;//卖出的总股数
    			for(int j=1;j<=n;j++) 
    			{
    				if(!q[j].is_del)
    					if(q[j].type==0 && q[j].p>=temp_price)//买入---将所有出价至少为p0的买单
    						sum1+=q[j].s;
    					else if(q[j].type==1 && q[j].p<=temp_price)//所有出价至多为p0的卖单 
    						 	sum2+=q[j].s;		
    			}
    			
    			
    			
    			
    			
    			LL k=min(sum1,sum2);//现如今能够成交(有人买&&有人卖)的最大数量 
    			if(k>max_s || (k==max_s && temp_price>max_price))
    			{
    				max_s=k;
    				max_price=temp_price;
    			}
    		}
    		
    		
    		
    	 printf("%.2lf %lld",max_price,max_s);
    	
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    201403-2-csp-窗口

    AcWing 3198. 窗口

    #include 
    using namespace std;
    const int N = 15;
    int n, m;		//n个窗口,m次点击 
    struct Window	//存储每个窗口信息 
    {
        int x1, y1, x2, y2;
        int id;		//窗口的编号 
    }w[N];
    
    int get(int x, int y)//得到---点击位置处于的窗口id是多少 
    {
        for (int i = n; i; i -- )		//从顶层一个个查看 ---因为顶层的优先级最高
            if (x >= w[i].x1 && x <= w[i].x2 && y >= w[i].y1 && y <= w[i].y2)
                return i;			
        return 0;			//没有点击到窗口 
    }
    
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i ++ )
        {
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            w[i] = {x1, y1, x2, y2, i};
        }
    
        while (m -- )
        {
            int x, y;
            cin >> x >> y;
            int t = get(x, y);
            if (!t) puts("IGNORED");	//没有点击到窗口 
            else
            {
                cout << w[t].id << endl;	//输出点击到窗口的id号 
               		
                for (int i = t; i < n; i ++ ) //将id号为t的窗口置顶 
    				swap(w[i],w[i + 1]);
                
            }
        }
    
        return 0;
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    AcWing 3426. 糖果分享游戏

    AcWing 3426. 糖果分享游戏

    #include
    using namespace std;
    const int N=1e2+10;
    int n;
    int a[N];
    int b[N];
    int main()
    {
    	while(cin>>n,n)//不断输入---直到0为止 
    	{
    		memset(a,0,sizeof(a));
    		for(int i=0;i<n;i++)
    			cin>>a[i];
    		
    	
    		int cnt=0;//记录第几轮
    		
    		while(true)
    		{
    			//先判断是否相同了 
    			bool is_same=true;
    			for(int i=0;i<n;i++)
    				if(a[i]!=a[0])
    					is_same=false;
    			if(is_same)
    				break;
    			
    			cnt++;//轮次++ 
    			
    			
    			for(int i=0;i<n;i++)
    				b[i]=a[i];//辅助数组 ---保存上一时刻的状态
    				
    			
    				
    			for(int i=0;i<n;i++)
    			{
    				a[i]=b[i]/2+b[(i-1+n)%n]/2;//计算 
    			}
    			for(int i=0;i<n;i++)
    			{
    				if(a[i]%2!=0)  a[i]++;//老师补给单数糖果的人---一颗糖 
    			}
    				
    		 }
    		 cout<<cnt<<" "<<a[0]<<endl; 
     	 
    	}
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    矩阵扫描

    AcWing 756. 蛇形矩阵

    AcWing 756. 蛇形矩阵

    在这里插入图片描述

    #include
    using namespace std;
    const int N=1e2+10;
    int g[N][N];
    int n,m;
    int dx[4]={-1,0,1,0};//上右下左 
    int dy[4]={0,1,0,-1};//镜像对称 
    int main()
    {
    	cin>>n>>m;
    	int x=0,y=0;//起始点的坐标 
    	int d=1;//起始方向 
    	for(int i=1;i<=n*m;i++)
    	{
    		g[x][y]=i;
    		int a=x+dx[d];
    		int b=y+dy[d];
    		if(a<0||a>=n||b<0||b>=m||g[a][b])//如果越界 或者 撞墙 
    		{
    			d=(d+1)%4;//调转方向---上->右,右->下,下->左,左->上 
    			a=x+dx[d];//新的位置 
    			b=y+dy[d];
    		 } 
    		 x=a;//迭代坐标 
    		 y=b; 
    	}
    	for(int i=0;i<n;i++)
    	{
    		for(int j=0;j<m;j++)
    		{
    			cout<<g[i][j]<<" ";
    		}
    		cout<<endl;
    	 } 
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    201412-2-csp-Z字形扫描

    AcWing 3208. Z字形扫描

    在这里插入图片描述

    #include
    using namespace std;
    const int N =500+10;
    
    int g[N][N];
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			cin>>g[i][j];
    		}
    	}
    	for(int i=2;i<=2*n;i++)//[2,2*n]总共有2*n-1斜行 ---i=每个点的坐标和[a][b] a+b=i---a=j,b=i-j 
    	{
    		if(i%2==0)//奇数行---从左下到右上 
    		{
    			for(int j=i-1;j>=1;j--)//[j][i-j]---点的坐标 
    			{
    				if(j>=1&&j<=n && i-j>=1&&i-j<=n)
    					cout<<g[j][i-j]<<" ";
    			 } 
    		 } 
    		if(i%2!=0)//偶数行---从右上到左下 
    		{
    			for(int j=1;j<=i-1;j++)//[j][i-j]---点的坐标 
    			{
    				if(j>=1&&j<=n && i-j>=1&&i-j<=n)
    					cout<<g[j][i-j]<<" ";
    			 } 
    		 } 
    	}
    	cout<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    日期问题

    日期问题常用模板

    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数
    
    • 1
    bool is_leap_year(int y)//判断闰年----------是不是闰年-----0不是,1是 
    {
    	if(y%400==0 || y%4==0&&y%100!=0)
    		return true;
    	else 
    		return false; 
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    int get_day(int year,int month)//得到某年某月有多少天数 
    {
    	if(month==2)
    		return months[month]+is_leap_year(year);
    	else
    		return months[month];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    计数月,日或分钟等等

    计算日的算法如下,小时分钟和秒就是在此基础上乘以相应的进制即可,月份就是在模板里面month++的时候顺便计数即可。

    int syear,smonth,sday; //分别为结束年,月,日
    int countday(int year,int month,int day){  //分别为开始的年月日
    	int ans=0;
    	int mon[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    	while(1){
    		if(year==syear&&month==smonth&&day==sday){
    			break;
    		}
    		day++;
    		if(isleaf(year)&&month==2){
    			if(day>mon[month]+1){
    				month++;
    				day=1;
    			}
    		}else{
    			if(day>mon[month]){
    				month++;
    				day=1;
    			}
    		}
    		if(month>12){
    			month=1;
    			year++;
    		}
    		ans++;
    	}
    	return ans;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    AcWing 3607. 打印日期

    AcWing 3607. 打印日期
    天数模拟——按日枚举

    #include
    
    using namespace std;
    
    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数
    
    bool is_leap_year(int y)//判断闰年----------是不是闰年-----0不是,1是 
    {
    	if(y%400==0 || y%4==0&&y%100!=0)
    		return true;
    	else 
    		return false; 
     } 
    
    int get_day(int year,int month)//得到某年某月有多少天数 
    {
    	if(month==2)
    		return months[month]+is_leap_year(year);
    	else
    		return months[month];
    }
    
    int main()
    {
    	int y,d;
    	while(scanf("%d%d",&y,&d)!=EOF)
    	{
    		int day=0,month=1;//枚举天数
    		while(d--)
    		{
    			//如果天数>该月份的天数,则月份++,天数归1
    			if(++day>get_day(y,month))
    			{
    				if(++month>12)//如果月份大于12,则年份++,月份归1
    				{
    					month=1;
    					y++;
    				}
    				day=1;
    			}	 			
    		 }
    	printf("%04d-%02d-%02d\n",y,month,day); 
    		
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    前缀和计算——按月枚举

    #include
    
    using namespace std;
    
    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数
    int pre_month_day[13];//前缀和数组 
    
    bool is_leap_year(int y)//判断闰年----------是不是闰年-----0不是,1是 
    {
    	if(y%400==0 || y%4==0&&y%100!=0)
    		return true;
    	else 
    		return false; 
     } 
    
    int get_day(int year,int month)
    {
    	if(month==2)
    		return months[month]+is_leap_year(year);
    	else
    		return months[month];
    	
    }
    
    int main()
    {
    	int y,d;
    	while(scanf("%d%d",&y,&d)!=EOF)
    	{
    		int day=0,month=1;
    		for(int i=1;i<=12;i++)//枚举月数
    		{
    			pre_month_day[i]=pre_month_day[i-1]+get_day(y,i);//前i个月份的天数和 
    			
    			if(d<=pre_month_day[i])//如果前i个月的天数>=设定的天数
    			{
    				day=d-pre_month_day[i-1];
    				month=i;
    				break;
    			}
    			if(d>pre_month_day[i]&&i==12)//如果设定的天数大于整年的天数,那么一定是下一年
    			{
    				y++;
    				month=1;	
    			}
    				
    		 } 
    	printf("%04d-%02d-%02d\n",y,month,day); 
    		
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    201509-2csp日期计算—上一个题的按月模拟版

    用到了一维前缀和

    AcWing 3218. 日期计算

    #include
    using namespace std;
    
    int y,d;
    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数
    int a[13];
    bool check(int y)//是不是闰年-----0不是,1是 
    {
    	if(y%400==0 || y%4==0&&y%100!=0)
    		return true;
    	else 
    		return false; 
     } 
     
     int main()
     {
     	cin>>y>>d;
     	if(check(y)) 
     		months[2]=29;
     	else	
     		months[2]=28;
     	for(int i=0;i<13;i++)
     		a[i]=a[i-1]+months[i];//前缀和数组
    
    	for(int i=0;i<13;i++)
    	{
    		if(a[i]<d && d<=a[i+1])
    		{
    			cout<<i+1<<endl;
    			cout<<d-a[i]<<endl;
    			break;
    		}
    		
    	 } 
     	return 0;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    AcWing 3573. 日期累加

    AcWing 3573. 日期累加

    #include
    
    using namespace std;
    
    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数
    int pre_month_day[13];//前缀和数组 
    
    bool is_leap_year(int y)//判断闰年----------是不是闰年-----0不是,1是 
    {
    	if(y%400==0 || y%4==0&&y%100!=0)
    		return true;
    	else 
    		return false; 
     } 
    
    int get_day(int year,int month)//得到某年某月有多少天数 
    {
    	if(month==2)
    		return months[month]+is_leap_year(year);
    	else
    		return months[month];
    }
    
    
    int get_year_days(int year,int month)//获得year年第month月--year + 1年第month月的的天数
    {
    	if(month<=2)
    		return 365+is_leap_year(year);
    	else
    		return 365+is_leap_year(year+1);
    }
    
    int main()
    {
    	int T;
    	cin>>T;
    	while(T--)
    	{
    		int y,m,d,a;
    		cin>>y>>m>>d>>a;
    		if(m==2&&d==29)//闰年二月份特殊一天的特殊处理
    		{
    			a--,m=3,d=1;
    		}
    		while(a>get_year_days(y,m))//按年枚举
    		{
    			a-=get_year_days(y,m);
    			y++;
    		 }
    		 while(a--)//按天枚举 
    		 {
    		 	if(++d>get_day(y,m))
    		 	{
    		 		if(++m>12)
    		 		{
    		 			m=1;
    		 			y++;
    				 }
    				d=1;
    			 }	
    		  } 
    	printf("%04d-%02d-%02d\n",y,m,d);		
    	 } 
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    AcWing 1341. 十三号星期五

    AcWing 1341. 十三号星期五
    在这里插入图片描述

    #include
    using namespace std;
    
    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数
    int weekday[7];
    bool is_leap_year(int y)//判断闰年----------是不是闰年-----0不是,1是 
    {
    	if(y%400==0 || y%4==0&&y%100!=0)
    		return true;
    	else 
    		return false; 
     } 
    int main()
    {
    	int n;
    	cin>>n;
    	int days=0;
    	for(int year=1900;year<1900+n;year++)//遍历年份
    	{
    		for(int i=1;i<=12;i++)//遍历月份
    		{
    			weekday[(days+12)%7]++;
    			days+=months[i];
    			if(i==2)
    			{
    				if(is_leap_year(year))
    				days++;
    			}
    		}
    	}
    	
    	for(int i=5,j=0;j<7;i=(i+1)%7,j++)
    	{
    		cout<<weekday[i]<<" ";
    	}
    	cout<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    201503-3csp节日

    AcWing 3214. 节日
    按月份枚举

    #include
    using namespace std;
    //12个月,开13个位置,0为占位符
    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数
    
    bool is_leap_year(int year)
    {
    	if( year%400==0 || year%4==0&&year%100!=0 )
    		return true;
    	else
    		return false;
     } 
    int get_year_day(int year)
    {
    	return 365+is_leap_year(year);
    }
    
    int get_month_day(int year,int month)//求某月有多少天的函数
    {
    	if(month==2)
    		return months[month]+is_leap_year(year);
    	else
    		return months[month];
    }
    
    int main()
    {
    	int a,b,c,y1,y2;
    	cin>>a>>b>>c>>y1>>y2;
    	int days=0;//表示从1850年1月1日起---过了多少天
    	for(int y=1850;y<=y2;y++) 
    		for(int m=1;m<=12;m++)
    		{
    			if( y>=y1 && m==a )
    			{	//星期一到星期日用0~6表示
    				int w=(days+1)%7;//表示从1850年1月1日开始---到这个月1日--一共经过了days+1天 ---且1850年1月1日是星期二,w下标=1 
    				int cnt=0;//统计一下当前是枚举到的第几个星期c
    				
    				for(int d=1;d<=get_month_day(y,m);d++) 
    				{
    					if(w==c-1)//星期的下标从0开始,所以要-1,如星期七的下标是6
    						cnt++;
    					if(cnt==b)//如果星期c的个数等于b的话,满足条件,输出
    					{
    						printf("%04d/%02d/%02d\n",y,m,d);
    						break;
    					}
    					w=(w+1)%7;//每过一天,星期需要往后错一位
    				}
    				if(cnt<b)//枚举完这个月后,如果星期c出现的次数小于b,说明没有第b个星期c,输出none
    					cout<<"none"<<endl;
    				
    				
    			 } 
    			days+=get_month_day(y,m);//这个月过完之后+这个月的天数 
    		}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    结构体排序

    有关字符串的排序
    sort用法

    bool operator < (const Person& t) const
    {
    	if(score!=t.score)
    		return score<t.score;
    	int stringcmp = strcmp(name,t.name);
    	if(stringcmp!=0)
    		return stringcmp<0;
    	else
    		return age<t.age;
    }
    函数原型:int strcmp(const char* str1, const char* str2)
    
    头  文  件:#include <string.h>
    返  回  值:str1 = str2   则返回0,
                       str1 > str2  则返回大于0的值,
                       str1 < str2  则返回小于0的值
    说明:
    判断两个字符串大小
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    AcWing 3375. 成绩排序

    AcWing 3375. 成绩排序

    相同元素的次序不发生变化的排序——稳定排序
    C++中stable_sort(稳定排序—归并排序)和sort(不稳定排序—快速排序)的区别——用法一致
    信息存储——结构体

    #include
    
    using namespace std;
    const int N = 1010;
    
    int n,m;
    struct Person
    {
    	string name;
    	int score;
    	//定义结构体的比较方式——重载运算符
    	bool operator < (const Person& t) const
    	{
    		return score < t.score;
    	}
    	bool operator > (const Person& t) const
    	{
    		return score > t.score;
    	}
     } q[N];
     
    int main()
    {
    	cin>>n>>m;
    	for(int i=0;i<n;i++)
    	{
    		cin>>q[i].name>>q[i].score;
    	}
    	if(m==0)
    		stable_sort(q,q+n,greater<Person>());
    	else
    		stable_sort(q,q+n);
    		
    	for(int i=0;i<n;i++)
    	{
    		cout<<q[i].name<<" "<<q[i].score<<endl;
    	}
    	
    	return 0;
    	
    	
    	 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    AcWing 429. 奖学金

    多关键字排序——重载结构体运算符
    AcWing 429. 奖学金

    #include
    using namespace std;
    
    const int N=310;
    
    struct Person 
    {
    	int id, sum, a, b, c;
    	bool operator<(const Person& t)const
    	{
    		if(sum!=t.sum) return sum>t.sum;//总分成绩最高的排在前面
    		if(a!=t.a)	return a>t.a;//语文成绩高的在前面
    		return id<t.id;//学号小的在前面 
    	}
     } q[N];
     
     int n;
     int main()
     {
     	cin>>n;
     	for(int i=1;i<=n;i++)
     	{
     		int a,b,c;
     		cin>>a>>b>>c;
     		q[i]={i,a+b+c,a,b,c};
     		
    	 }
    	 sort(q+1,q+n+1);
    	 
    	 for(int i=1;i<=5;i++)
    	 {
    	 	cout<<q[i].id<<" "<<q[i].sum<<endl;
    	 }
    	 return 0;
      } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    201803-2-csp-碰撞的小球

    AcWing 3258. 碰撞的小球

    #include
    using namespace std;
    
    const int N=1e2+10;
    
    struct node{
    	int id;//原来的次序
    	int dir=1;//记录方向 1右 -1左
    	int pos;//位置坐标 
    	bool operator<(const node &t)const//重载运算符----位置下标小的在前 
    	{
    		return pos<t.pos;
    	 } 
    }q[N]; 
    
    bool cmp(node x , node y)//重载比较函数 
    {
    	return x.id<y.id;
    }
    int n,L,t; 
    int main()
    {
    	cin>>n>>L>>t;
    	for(int i=0;i<n;i++)
    	{
    		cin>>q[i].pos;
    		q[i].id=i;
    	 } 
    	 sort(q,q+n);//按初始位置排序 
    	
    	while(t--)//模拟经过t秒 
    	{
    		for(int j=0;j<n;j++)
    		{
    			
    			//方向变化 
    			if(q[j].pos==L||!q[j].pos)		q[j].dir*=-1;
    				
    			if(q[j].pos==q[j+1].pos)
    			{
    				q[j].dir*=-1;
    				q[j+1].dir*=-1;
    			}
    			//移动 
    			q[j].pos+=q[j].dir; 
    			
    		}		
    	}
    	sort(q,q+n,cmp);//按初始的id排序 ---因为上面排了次顺序,打乱了原来的次序
    	for(int i=0;i<n;i++)
    		cout<<q[i].pos<<" ";
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    不用排序的暴力枚举法

    #include
    using namespace std;
    const int N = 110;
    int n, L, T;
    
    struct Ball
    {
        int pos, dir;
    }b[N];
    
    int main()
    {
        cin >> n >> L >> T;
        for (int i = 0; i < n; i ++ )
        {
            cin >> b[i].pos;
            b[i].dir = 1;
        }
        while (T -- )
        {
            for (int i = 0; i < n; i ++ )
            {
                b[i].pos += b[i].dir;//移动一步
    			 
                if (b[i].pos == L || !b[i].pos)//如果跑到0/l处---撞墙---反向 
                    b[i].dir *= -1;
            }
            
            //因为初始时,小球的位置随机---所以遍历所有的小球找到相撞的小球
            for (int i = 0; i < n; i ++ ) 
                for (int j = i + 1; j < n; j ++ )
                    if (b[i].pos == b[j].pos)
                    {
                        b[i].dir *= -1;
                        b[j].dir *= -1;
                    }
        }
        for (int i = 0; i < n; i ++ )//按照起始位置输出 
            cout << b[i].pos << ' ';
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    201709-2-csp公共钥匙盒—还钥匙/取钥匙分为两种操作—拆点法

    AcWing 3248. 公共钥匙盒

    1定义一个结构体,记录时间、操作类型、钥匙编号;
    
    2. 在结构体中,根据题目意思,按照时间、类型、编号的先后顺序,分别对时间从小到大排序,先还后取,编号从小到大排序;
    
    3. 在输入的时候,将取钥匙操作和还钥匙操作一起加入到结构体中;
    
    4. 对结构体按照2.中思路进行排序;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    #include
    using namespace std;
    const int N=1e3+10;
    int n,k;
    struct node{
    	int t;//时间
    	int type;//操作类型----0 取钥匙   1  还钥匙
    	int id;//编号 
    	bool operator<(const node &x) const		//---多关键字排序 
    	{
    		if(t!=x.t)	return t<x.t;//时间小的在前
    		if(type!=x.type) return type>x.type;//还钥匙在取钥匙操作前
    		return id<x.id;//编号小的在前 
    	}
    }op[N*2];
    int p[N];//钥匙盒 
    int main()
    {
    	cin>>n>>k;
    	 int j=1;//记录结构体中有多少个元素,用于排序;
    	for(int i=1,id,start,len;i<=k;i++)
    	{
    		cin>>id>>start>>len;
    		op[j++]={start,0,id};
    		op[j++]={start+len,1,id};
    	}
    	for(int i=1;i<=n;i++) p[i]=i;//钥匙盒中的钥匙id 
    	
    	sort(op+1,op+j+1);//排序
    	
    	for(int i=1;i<=j;i++)
    	{
    		if(op[i].type==0)//取钥匙 
    		{
    			for(int k=1;k<=n;k++)
    				if(p[k]==op[i].id)
    				{
    					p[k]=0;//取走钥匙
    					break; 
    				}
    		}
    		else//还钥匙操作 
    		{
    			for(int k=1;k<=n;k++)
    				if(p[k]==0)
    				{
    					p[k]=op[i].id;//把钥匙放入钥匙盒
    					break; 
    				}
    		 } 
    	 } 
    	 
    	 for(int i=1;i<=n;i++)
    	 	cout<<p[i]<<" ";
    	
    	
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    201503-2-csp-数字排序

    AcWing 3213. 数字排序

    
    #include
    using namespace std;
    int n;
    const int N=1e3+10;
    typedef pair<int,int> PII;
    PII node[N];
    bool cmp(PII x,PII y)
    {
    	if(x.first!=y.first)
    		return x.first>y.first;
    	else
    		return x.second<y.second;
    		
    }
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		int k;
    		cin>>k;
    		node[k].first++;
    		node[k].second=k;
    	}
    	sort(node,node+N,cmp);
    	  //当出现first为0时终止
        for(int i=0;i<n && node[i].first!=0;i++)
        {
            cout<<node[i].second<<" "<<node[i].first<<endl;
        }
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    字符串

    字符串常用操作—字符串本质是字符数组

    读写字符串

    1. cin>>str;     单字符串输入,读入字符串,遇到空格或回车停止
    但需要注意的是
    只有按下回车键时才会结束输入执行;
    当按下空格后还能继续输入,但最终存到字符串中的只是第一个空格之前输入的字符串
    
    2. getline(cin,str);		在最终读入的字符串中保留空格---经常搭配getchar()函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    查询字符串信息、索引

        cout << str.empty() << endl;   str 为空返回 true,否则返回 false
        cout << str.size() << endl;    返回 str 中字符个数,不包含空字符
    
    • 1
    • 2

    拼接、比较等操作

    s1+s2           返回 s1 和 s2 拼接后的结果。
    s1 == s2        如果 s1 和 s2 中的元素完全相等则它们相等,区分大小写
    s1 != s2
    <, <=, >, >=    利用字符的字典序进行比较,区分大小写
    
    • 1
    • 2
    • 3
    • 4

    for 循环遍历

    如果想要改变 string 对象中的值,必须把循环变量定义为引用类型
    for(auto &c : str)  
    
    • 1
    • 2

    string 搜索操作

    作用为查找字符或字符串;
    查找成功则返回第一个字符或者字串的位置
    查找失败则返回string::npos 即为 -1
    s.find(args)  // 查找 s 中 args 第一次出现的位置
    s.rfind(args)  // 查找 s 中 args 最后一次出现的位置
    
    • 1
    • 2
    • 3
    • 4
    • 5

    提取子串—substr() 函数

    可以提取 string 字符串中的子字符串;
    该函数有两个参数:第一个参数为需要提取的子字符串的起始下标,第二个参数是需要提取的子字符串的长度
    string s = str.substr(6, 6);
    从str字符串的第六个字符开始---提取六个字符---放入字符串s中
    
    • 1
    • 2
    • 3
    • 4

    AcWing 3439. 首字母大写

    AcWing 3439. 首字母大写

    /*
    字符串处理 - 首字母大写。
    
    【本题思路】
        (1)由于需要特殊判断空格,利用 getline() 方法直接读取一行数据。
        (2)对每个字符进行判断,若其为首字母/前面为空格,说明它是某个单词的首字母,需要转化为大写字母。
        (3)转化为大写字母利用 toupper() 方法。
    
    【注意点】
        (1)由于需要特殊判断空格,不能使用常规的 cin 或者 scanf,因为它们会自动忽略空格。
        (2)通常利用 getline() 方法读取包含空格的字符串。注意该方法的参数:1) 输入流 &istream,2) 存储输入流信息的字符串 &s。
        (3)注意利用 toupper() 方法转化小写字母后,需要强制转换为 char 类型,否则输出为 ASCII 码。
    
     */
    
    #include
    using namespace std;
    
    int main()
    {
    	string str;
    	getline(cin,str);
    	for(int i=0;i<str.size();i++)
    	{
    		if(!i||str[i-1]==' ')
    			cout<<(char)toupper(str[i]);//如果是小写字母的话,则转化为大写字母,否则不变 
    		else
    			cout<<str[i]; 
    	}
    	return 0;
     } 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    AcWing 3504. 字符串转换整数

    AcWing 3504. 字符串转换整数

    #include
    using namespace std;
    typedef long long LL;
    
    int main()
    {
    	string str;
    	cin>>str;
    	
    	for(int i=0;i<str.size();i++)
    	{
    		int j=i;//从i到j-1的位置上都是数字
    		LL ans=0;
    		if(isdigit(str[i]))
    		{
    			while(j<str.size() && isdigit(str[j]))
    			{
    				ans=ans*10+str[j]-'0';
    				j++;
    				
    				if(ans>INT_MAX)
    				{
    					cout<<-1<<endl;
    					return 0;
    				}
    			}
    			i=j;
    			
    		cout<<ans<<endl; 
    	    return 0;
    		
    		}
    			
    	}
        cout<<-1<<endl;//如果没有输入的字符串中没有数字时
        return 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    AcWing 3406. 日志排序

    AcWing 3406. 日志排序

    #include
    using namespace std;
    const int N=1E4+10;
    
    string lines[N];
    int n;//n从0开始 
    
    bool cmp(string &a,string &b)
    {
    	
    		stringstream ssina(a),ssinb(b);//使用string流读取a,b行字符串
    		
    		string sa[4],sb[4];
    		for(int i=0;i<4;i++)
    		{
    			ssina>>sa[i];
    			ssinb>>sb[i];
    		 }
    		if(sa[3]==sb[3])//消耗时间相同时---对比日期---日期小的在前 
    			return sa[1]+sa[2]<sb[1]+sb[2];
    		
    		double ta,tb;//消耗时间的格式不同一,只好用格式读取
    		sscanf(sa[3].c_str(),"%lf(s)",&ta);
    		sscanf(sb[3].c_str(),"%lf(s)",&tb);
    		
    		return ta<tb; 
    		 
    }
    int main()
    {
    	while(getline(cin,lines[n]))
    	{
    		if(lines[n].size()) n++;
    		else break;
    	 }//读入结束
    	 
    	sort(lines,lines+n,cmp);
    	
    	for(int i=0;i<n;i++)
    		cout<<lines[i]<<endl;
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    201312-2-csp-ISBN号码

    AcWing433. ISBN号码

    #include 
    #include 
    
    using namespace std;
    
    int main()
    {
        string str;
        cin >> str;
        int sum = 0;
        for (int i = 0, j = 1; i + 1 < str.size(); i ++ )
            if (str[i] != '-')
            {
                sum += (str[i] - '0') * j;
                j ++ ;
            }
        sum %= 11;
        char c = 'X';
        if (sum < 10) c = '0' + sum;
        //得到了正确的最后一位 
        
        if (c == str[str.size()-1])//如果正确 
    		puts("Right");
        else//如果错误 
        {
            str[str.size()-1] = c;
            cout << str << endl;
        }
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    AcWing 1204.错误票据(stringstream读取)

    acwing1204错误票据

    难点在于读取数据上 使用了stringstream 来读取

    #include
    using namespace std;
    const int N= 1e4+10;
    int a[N];//存储id号 
    int cnt;//a[N]的下标 
    int m,n;//m---断号   n---重号 
    int main()
    {
    	int T;//数据的行数
    	string line; 
    	cin>>T;
    	getchar();//读取上行代码中输入的回车符 ---方便下面的getline函数的读入 
    	while(T--)
    	{
    		getline(cin,line);//将一整行读入到line中去 
    		stringstream ssin(line);//定义字符流,从line中读取小字符串 
    		
    		while(ssin>>a[cnt]) cnt++;//以空格为分隔符,把line里面的字符输出到a[]数组中,这里会自动类型转换
    	}
    	sort(a,a+cnt);
    	for(int i=1;i<cnt;i++)//从第二个数据开始 
    	{
    		if(a[i]==a[i-1]) n=a[i];//缺失(断号)
    		if(a[i]==a[i-1]+2) m=a[i]-1;
    	}
    	cout<<m<<" "<<n<<endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    201403-3-命令行选项

    AcWing 3199. 命令行选项

    题目描述
    
    问题分析 :
    从第3行开始对于每个输入的字符串内是否存在合理的 第一行输入的各种选项中
    合理的就继续输出 不合理的直接结束,下一行
    
    重点分析 :
    1. 存储合理的选项 st1, st2;
    2. 记录字母存放参数的ans
    
    注意 :
    模拟题细节挺多的
    1. 使用sstream 前 getchar(); // 除去输入n后边的换行
    2. 学习sstream语法
    3. 字符串与数值间的转化
    4. 对于有参的选项 处理时要i++;
    5. 做新的输入时要把ans清空
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    #include
    using namespace std;
    const int N=30;
    bool st1[N];
    bool st2[N];
    string ans[N];
    int main()
    {
    	string str;
    	getline(cin,str);//读取第一行 
    	for(int i=0;i<str.size();i++)//对第一行的选项分类---无参数选项---带参数选项 
    	{
    		if(str[i+1]==':'&&i+1<str.size())//要保证:至少是倒数第2位
    		{
    			st2[str[i]-'a']=true;//带参数 
    			i++;//跳过:
    		}
    		else
    			st1[str[i]-'a']=true;//无参数 
    	}
    	int n;
    	cin>>n;
    	getchar();
    	
    	
    	
    	for(int C=1;C<=n;C++)
    	{
    		string line;
    		getline(cin,line);//读取一行大字符串
    		stringstream ssin(line);//定义字符串流---读取大字符串中的小字符串
    		vector<string> vec;//存储小字符串
    		while(ssin>>str) vec.push_back(str);//将大字符串中的小字符串读入到str中去
    		
    		for(int i=0;i<N;i++) 
    			ans[i].clear();
    		for(int i=1;i<vec.size();i++)//从1开始---跳过ls 
    		{
    			if(vec[i][0]!='-'||vec[i][1]<'a'||vec[i][1]>'z'||vec[i].size()!=2)
    				break;//说明此时的选项输入非法
    				
    			int k=vec[i][1]-'a';//字符的字典序
    			
    			if(st1[k])//当属于无参数选项时
    				ans[k]='*';//保证命令不为空
    				
    			else if(st2[k]&&i+1<vec.size())//当属于有参数选项时
    				ans[k]=vec[i+1],i++;//注意---i++用来跳过参数
    				
    				else break; //否则的话---说明选项不合法---出现原本没有的选项字母
    		}
    		
    		
    		
    		
    		cout<<"Case "<<C<<":";
    		for(int i=0;i<26;i++)
    		{
    			if(ans[i].size())//如果有合法的输入---无参数选项/有参数选项
    			{
    				cout<<" -"<<char(i+'a');
    				if(st2[i])//如果是带参数的---输出参数
    					cout<<" "<<ans[i];
    			}
    		}
    		cout<<endl;
    	}
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    AcWing1231.航班时间(时间模拟+时差处理+字符串处理)

    AcWing1231.航班时间

    /*
        常识问题:关于时差
        由于地球自西向东自转造成东早西晚:
            西->东:相差+时差
            东->西:相差-时差
        分析:由于题干说飞机来回时长视为相等,航行不知道是东向西还是西向东,也不知道时差是多少
              但是  来+回=来相差-时差+回相差+时差,所以来回时间和与时差无关
              另外需要注意的是题干问的“飞机的飞行时间”是要求单程的时间
              那么答案就是(来相差+回相差)/2
        计算思路:主要算两个相差
                1.将所有的时间化成距离当天00:00:00的秒数(由于两个时间直接作差较难,因此先转化称距离当天00:00:00的秒数再进行计算),跨天的再加上d*24*3600
                2.结果输出,即秒数转化为“时:分:秒”,采用“水仙花”算法。
                hour=time/3600;
                minute=time%3600/60;
                second=time%60
                为了简洁性,可以用get_time自定义子函数来处理相差,用get_seconds自定义子函数来求距离
            00:00:00的秒数
    
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
        本题难点:处理输入输出,用getline
                需要注意的是getline会读入回车,因此要手动写一行用来忽略回车
                输入处理:当没有(+1),或者(+2)时候,手动添加(+0),使得输入格式统一,均为h:m:s (+d)
                另外就是一个back和c_str库函数的用法
                c_str用于返回str类
                输出:前导零的处理,用%02d解决
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    
    
    #include
    using namespace std; 
    int n;
    int get_seconds(int h,int m,int s)
    {
    	return h*3600+m*60+s;
    }
    
    int get_time()//求来或者回的相差         
    {
    	string line;
    	getline(cin,line);//将以后的所有输入,全都读取进来了 
    	if(line.back()!=')') line+="(+0)";//补充成统一的格式
    	int h1,m1,s1,h2,m2,s2,d;
    	sscanf(line.c_str(),"%2d:%2d:%2d %d:%d:%d (+%d)",&h1,&m1,&s1,&h2,&m2,&s2,&d);
    	//sscanf()会将参数str的字符串根据参数format字符串来转换格式并格式化数据。
        //转换后的结果存于对应的参数内。
        //函数c_str()就是将C++的string转化为C的字符串数组
    	return get_seconds(h2,m2,s2)-get_seconds(h1,m1,s1)+d*3600*24;
    }
    int main()
    {
    	cin>>n;
    	getchar();	 //手动忽略回车
    	while(n--)
    	{
    		int time=(get_time()+get_time())/2;		//(来+回=来相差-时差+回相差+时差)/2 并转化为具体的秒数
    		int hour=time/3600,minute=time%3600/60,second=time%60;
    		printf("%02d:%02d:%02d\n",hour,minute,second);	//按照格式输出
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    201409-3-csp-字符串匹配

    AcWing 3204. 字符串匹配

    #include
    using namespace std;
    const int N=1e2+10;
    
    int n;
    string get(string str)//将字符串的字母大写转为小写
    {
    	string res="";
    	for(auto t:str)
    	{
    		res+=tolower(t);
    		//res+=toupper(t);小写转大写---toupper
    	}
    	return res;
    }
    int main()
    {
    	string S;
    	cin>>S;
    	int type,n;//type:0为不区分大小写
    	cin>>type>>n;
    	while(n--)
    	{
    		string str;
    		cin>>str;
    	//string 的find函数---找到与给定字符串相匹配的第一个字符的位置,找不到返回-1
    		if(type && str.find(S)!=-1)	cout<<str<<endl;//(find函数o(n^2)时间复杂度)
    		if(!type && get(str).find(get(S))!=-1)	cout<<str<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    201604-3-csp-路径解析

    AcWing 3229. 路径解析

    #include
    using namespace std;
    
    int n;
    vector<string> get(string str)//将原本带有'/'的路径---转化为不带有'/'的路径 
    {
    	vector<string> res;
    	for(int i=0;i<str.size();i++)
    	{
    		if(str[i]=='/')	continue;  
    		int j=i+1;
    		while(j<str.size() && str[j]!='/') j++;
    		res.push_back(str.substr(i,j-i));
    		i=j;
    	}
    	return res;
     } 
     
     void walk(vector<string> cur,vector<string> path)//按照给定的路径走 
     {
     	for(auto c:path)
     	{
     		if(c==".")	continue;//当前目录---不用处理 
     		if(c=="..")//返回上级
    		 {
    		 	if(cur.size())//从当前目录返回一级 
    			 	cur.pop_back(); 
    		  } 
    		 else
    		 	cur.push_back(c);//从当前目录,往c走 
    	 }
    	 
    	 
    	 //走完该条路径后 
    	 if(cur.empty())//cur为空时,不用走 
    	 {
    	 	cout<<"/"<<endl; 
    	 	return ;
    	 }
    	 for(auto t:cur)//输出每个字符串正规化后的   绝对路径 ==当前路径+新走的路径 
    	 {
    	 	cout<<"/"<<t;
    	 }
    	cout<<endl;
    	return ;
     }
     
    int main()
    {
    	cin>>n;
    	string str;//输入--当前目录 
    	cin>>str;
    	getchar();// 过滤换行
    	vector<string> cur=get(str);//cur表示的是相对路径
    	
    	vector<string> ab;//ab表示绝对路径 ---从根目录开始,所以起始为空 
    	
    	while(n--)
    	{
    		string line;
    		getline(cin,line);//一次读入一行 
    		
    		auto path=get(line);//将路径去除'/'
    		
    		if(line.size() && line[0]=='/') 
    			walk(ab,path);//是绝对路径 
    		else
    			walk(cur,path);//只是沿着当前路径走---并未修改当前路径,所有走完之后,当前路径不变 
    	 } 
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    201509-3-csp-模板生成系统

    AcWing 3219. 模板生成系统
    详细题解—ccfcsp大全

    转义字符

    #include
    using namespace std;
    vector<string> strs;
    unordered_map<string,string> vars;
    
    int main()
    {
    	int m,n;
    	cin>>m>>n;
    	getchar(); //过滤cin读剩下的回车
    	while(m--)
    	{
    		string str;//一次读入一行 
    		getline(cin,str);
    		strs.push_back(str);
    	}
    	while(n--)
    	{
    		string key,value;
    		cin>>key;//因为key中没有空格---所有可以使用cin读入,不然getline
    		char c; //变量值含空格和双引号,用getchar()读
    		while(c=getchar(),c!='\"');//过滤第一个引号之前的内容
    		while(c=getchar(),c!='\"') value+=c;
    		vars[key]=value;//存入哈希表 
    	}
    	for(auto & str:strs)//因为需要修改每一行的字符串---所以使用引用 
    	{
    		for(int i=0;i<str.size();)
    		{
    			if(i+1<str.size() && str[i]=='{' && str[i+1]=='{')//如果需要替换变量
    			{
    				int j=i+3;//跳过变量开始的括号+空格
    				string key;
    				while(str[j]!=' ' || str[j+1]!='}' || str[j+2]!='}')//变量还没有到达结尾时
    					key+=str[j++];//读取模板中的变量
    				cout<<vars[key]; //哈希表替换模板中的值---如果不存在,哈希表自动处理为空 
    				i=j+3;//处理完之后要跳过空格和两个右括号 
    			}
    			else
    				cout<<str[i++]; //不需要替换变量,直接输出模板
    		 }
    		 cout<<endl; 
    	 } 
    	
    	
    	
    	
    	return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    AtCoder Beginner Contest 262 部分题解
    自然语言处理(NLP)—— 信息提取与文档分类
    霓虹【算法赛】蓝桥杯第7场强者挑战赛
    嘉为蓝鲸受邀参加2022(第十届)国际智慧机场发展论坛
    Ali-Sentinel-Spring WebMVC 流控
    36 | SRE的工作职责
    Vue 常用指令
    分布式搜索引擎Elasticsearch基础入门学习
    外包干了10个月,技术退步明显.......
    云安全-云原生k8s攻击点(8080,6443,10250未授权攻击点)
  • 原文地址:https://blog.csdn.net/qq_50675813/article/details/133441782