3 条题解

  • 1
    @ 2025-11-4 22:49:14

    利用栈先算出单个最长的gold,并存到一个数组里面,然后单独讨论这个数组,满足gsg格式且有大于两串g的时候可以让前后两个长度相加再加1,如果gsg格式且只有2串,那就是前面加后面的长度,如果满足gsss(s>=2)g这个格式,就是前面或后面的长度加一,最后判断所有可能的长度的最大值,输出

    1. p是bb数组的索引
    2. bb数组存每一串连续gold的长度
    3. b是每一串连续gold的长度
    4. q就是p的复制,不过后面p被更改
    5. a是输入进去的初始char数组
    6. maxb代表最长的连续gold的长度
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,b,p,q;
    int bb[1002];
    int maxb=0;
    char a[1002];
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;i++)
    	{
    		cin>>a[i];
    	}
    	for(int i=0;i<n+1;i++)
    	{
    	if(a[i]=='G')b++;
    	if(a[i]!='G'&&a[i-1]=='G')
    	{
    		bb[p]=b;//前一个连续g的长度  
    		p++;
    		b=0;
    	}
    	maxb=max(maxb,b);//换前最长gold 
    	}
        for(int i=0;i<p;i++)
    	{
    		if(p>=2)
    		{
    			maxb=max(maxb,bb[i]+1);//多s重合交换逻辑	
    		}
    	} 
    	q=p;
    	p=-1;
    	for(int i=0;i<n+1;i++)//几种情况的gold交换 
    	{
    		if(a[i]!='G'&&a[i-1]=='G')
    			{
    				p++;
    				if(a[i+1]=='G'&&q>2)
    					{
    						b=bb[p]+bb[p+1]+1;
    						maxb=max(maxb,b);//换后最长gold 
    					}
    				if(a[i+1]=='G'&&q==2)
    				{
    					b=max(bb[p]+1,bb[p+1]+1);
    					b=max(b,bb[p]+bb[p+1]);
    					maxb=max(maxb,b);//换后最长gold 
    				} 
    			}
    	} 
    	cout<<maxb;
     } 
    
    
    • 1
      @ 2025-10-2 9:01:46

      交换奖杯以获得最长连续金奖,那么交换的对象只能是S和G,以此为基础,再考虑边缘情况和特殊情况即可。 、 其中计算最长G可以写函数,这里忘记直接头铁写了。

      #include<stdio.h>
      #include<string.h>
      #include<stdlib.h> 
      
      int main(){
      	int n;
      	scanf("%d",&n);
      	char a[n];
      	int i,j;
      	//获取输入,使用i和j作为循环控制变量
      
        
      	for(i=0;i<n;i++){
      		scanf(" %c",&a[i]);
      	}
      	
      	int zong=0;
      	for(i=0;i<n;i++){
      		if(a[i]=='G') zong++;
      	}
      	if(zong==0){
      		printf("0");
      		return 0;
      	}
      	if(zong==n){
      		printf("%d",n);
      		return 0;
      	}
      	//对于G的总数的一些特殊情况
      
        
      	int max=0, current=0; 
      	for(i=0;i<n;i++){
      		if(a[i]=='G'){
      			current++;
      			if(current>max) max=current;
      		}else{
      			current=0;
      		}
      	}
        //获取最长的G序列,在不交换的条件下
      	
      	for(i=0;i<n;i++){
      		if(a[i]=='G') continue;//只交换S和G
      		for(j=0;j<n;j++){
      			if(a[j]=='S' || i==j) continue;//只交换S和G
      			char temp=a[i];
      			a[i]=a[j];
      			a[j]=temp;
      			//执行交换
      
            //下述代码为交换之后计算最长G
      			current=0;
      			int curr_max=0;
      			int k;
      			for(k=0;k<n;k++){
      				if(a[k]=='G'){
      					current++;
      				if(current>curr_max) curr_max=current;
      				}else{
      					current=0;
      				}
      			}
      			if(curr_max>max) max=curr_max;
      			
      			temp=a[i];
      			a[i]=a[j];
      			a[j]=temp;
      //核心:实现任意的S和G交换判断长度
       
      			if(max==zong) break;
      		}
      		if(max==zong) break;
      	}
        //与最大个数作比较
      	
      	printf("%d",max);
      	return 0;
      }
      
      • 0
        @ 2025-10-14 11:27:47

        思路:先记录每一段金奖杯的始末位置,然后考虑他们连接的问题

        #include <iostream>
        #include <vector>
        using namespace std;
        
        // 每一段金奖杯的始末位置 
        struct strInfo
        {
            int beginIndex = 0, endIndex = 0;
            strInfo(int a, int b)
            {
                beginIndex = a;
                endIndex = b;
            }
        
            int getLength()
            {
                return endIndex - beginIndex + 1;
            }
        };
        
        int main()
        {
            int n; 
            cin >> n;
            char str[n];
            int beginIndex = 0, endIndex = 0;
            vector<strInfo> Infos;
            for (int i = 0; i < n; i++)
            {
                cin >> str[i];
                if (str[i] == 'G')
                {
                    endIndex = i; // 向后挪末位置 
                }
                else if (str[i] == 'S') // 遇到银奖杯,记录上一段金奖杯的末位置 
                {
                    if (beginIndex != endIndex || str[beginIndex] == 'G' /* 这一段金奖杯只有一个的情况 */)
                    {
                        Infos.push_back(strInfo(beginIndex, endIndex));
                    }
                    // 重置下一段金奖杯位置 
                    beginIndex = i + 1;
                    endIndex = i + 1;
                }
            }
        
        	// 记录最后一段金奖杯的位置 
            if (str[n - 1] == 'G')
            {
                Infos.push_back(strInfo(beginIndex, endIndex));
            }
        
        	// 没有金奖杯 
            if (Infos.size() == 0)
            {
                cout << 0 << endl;
                return 0;
            }
            else if (Infos.size() == 1) // 只有一段金奖杯 
            {
            	// 直接输出这一段金奖杯的长度 
                cout << Infos[0].getLength() << endl;
                return 0;
            }
        
            bool hasCloseStr = false; // 标记是否有紧挨着的两端金奖杯 如:GGGSGGS 
            int maxSingleStrLength = 0; // 记录单端最长的金奖杯长度 
        
            for (size_t i = 0; i < Infos.size(); i++)
            {
                if (Infos[i].getLength() > maxSingleStrLength)
                {
                    maxSingleStrLength = Infos[i].getLength(); // 获取最长长度 
                }
            }
        
            vector<int> closeStrIndex; // 若金奖杯段a和b紧挨着(b在a之后),记录a在Infos中的索引 
        
            for (size_t i = 0; i < Infos.size() - 1; i++)
            {
                if (Infos[i + 1].beginIndex - Infos[i].endIndex == 2)
                {
                    hasCloseStr = true;
                    closeStrIndex.push_back(i);
                }
            }
        
        	// 若没有紧挨着的金奖杯则输出最长的一段长度+1(因为可以挪一个金奖杯过来) 
            if (!hasCloseStr)
            {
                cout << maxSingleStrLength + 1 << endl;
                return 0;
            }
        
            int ans = 0;
            for (size_t i = 0; i < closeStrIndex.size(); i++)
            {
                int length = Infos[closeStrIndex[i]/* 前面提到的金奖杯段a的索引 */].getLength() + 
        					Infos[closeStrIndex[i] + 1/* 金奖杯段b的索引 */].getLength(); // a 和 b 的总长度(因为相邻,所以可以挪动a或b中的一个金奖杯将两段合二为一) 
                if (length > ans)
                {
                    ans = length;
                }
            }
        
            if (Infos.size() == 2) // 只有两段金奖杯,且他们紧挨着 
            {
                cout << ans << endl;
            }
            else
            {
                if (maxSingleStrLength > ans) // 连续两段还没有最长的单段长 
                {
                    cout << maxSingleStrLength + 1 << endl;
                    return 0;
                }
                
                // 有2段以上金奖杯,可以从其他地方挪一个金奖杯来连接最长的两段金奖杯,所以ans+1 
                cout << ans + 1 << endl;
            }
                
            return 0;
        }
        
        • 1

        信息

        ID
        307
        时间
        1000ms
        内存
        256MiB
        难度
        8
        标签
        递交数
        828
        已通过
        97
        上传者