zoukankan      html  css  js  c++  java
  • CF-div2-630-C

    思路

    1.与当前i相关联的有 i,i+k,i+2k n-i+1, n-i+1-k,n-i+1-2k... ,题目就是让我们把这些位置上的字符变成一样,花费的最小值
    2.考虑当前这个数a[i]的局部最优解,如何花费最小,贪心的想,肯定是把与它关联的 i,i+k,i+2k n-i+1, n-i+1-k... 这些字符改成这些字符串现次数最多的字符,(改成原次数出现最多的字符,就代表“这一轮一共修改的最少”),
    3.考虑贪心有没有bug,(2)中局部求最优解,但这样贪心并不一定整体就最优,想一想这样局部求最优是否有无后效性。即当前选择的结果必须不能对之前的结果状态产生影响!
    考虑i从1~n 肯定会出现判重复,对重复的数相关联的数再去修改就不能达到最优了!
    想到可以设置标记数组,来标记之前是否修改过,因为前面修改过的数肯定是用和它相关联的数来修改的,已经 把与他相关联的 做了修正 这次就不用考虑他了,也不用再考虑与它相关联的数了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int t,n,k,ans;
    const int maxn = 2e5+100;
    bool vis[maxn];
    char s[maxn]; 
    int cnt[30];
    
    void init(){
    	ans = 0;
    	for(int i=1;i<=n;i++) vis[i] = false;
    }
    
    void solve(){
    	cin>>n>>k;
    	scanf("%s",s+1);
    	init();
    	for(int i=1;i<=n;i++){
    		if(vis[i]) continue;
    		for(int j=0;j<27;j++) cnt[j] = 0;
    		int cnt1 = 0;
    		int mx = 0;
    		//与当前i相关联的有 i,i+k,i+2k  n-i+1, n-i+1-k... 
    		//考虑从1~n判 肯定会出现判重复 设置vis数组标记用过 
    		//因为前面用过的数肯定已经 把与他相关联的 做了修正 这次就不用考虑他了 
    		for(int j=i;j<=n;j+=k){ //k个一组 
    			if(!vis[j]){  //防止重复计算 
    				vis[j] = true;
    				cnt1++;
    				cnt[s[j] - 'a']++;
    				mx = max(cnt[s[j] - 'a'],mx);
    			}else break;  
    		}
    		for(int j=n-i+1;j>=1;j-=k){ //i对应的回文(另一端) k个一组 
    			if(!vis[j]){
    				vis[j] = true;
    				cnt1++;
    				cnt[s[j] - 'a']++;
    				mx = max(cnt[s[j] - 'a'],mx);
    			}else break;
    		}
    		ans += cnt1 - mx;
    	}
    	cout<<ans<<endl;
    }
    
    int main(){
    	cin>>t;
    	while(t--){
    		solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    改造我们的学习:有钱不会花,抱着金库抓瞎
    (转)我奋斗了18年才和你坐在一起喝咖啡
    初学者要知道的十件事
    [转]C#图像处理 (各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
    C#调用系统的复制、移动、删除文件对话框
    SQLite数据类型
    jquery禁用dropdownlist中某一项
    C# winform无标题窗体随意移动
    注册.NET Framework
    jQuery同步/异步调用后台方法
  • 原文地址:https://www.cnblogs.com/fisherss/p/12610856.html
Copyright © 2011-2022 走看看