题目:
###本题主要考察暴力,枚举,模拟
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int a[N],b[N];
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int num;cin>>num;//样例个数循环for(int i=1;i<=num;++i){int n,k,mi=INT_MAX;cin>>n>>k;//颜色入数组for(int j=1;j<=n;++j)cin>>a[j];//60种颜色遍历for(int j=1;j<=60;++j){int cnt=0;//保证数组初始化for(int h=1;h<=n;++h)b[h]=a[h];//每重案例 每种颜色 为每个房子遍历涂色for(int h=1;h<=n;++h){if(b[h]!=j){//操作k区间for(int z=h;z<=h+k-1;++z)b[z]=j;//下一次要操作的房子h+=k-1;cnt++;}}mi=min(mi,cnt);}cout<<mi<<'\n';}return 0;
}
整体思路:
- 颜色只有60种,可以将每一种情况对该k长度的区间的操作都遍历
- 循环j表示颜色,建两个数组只对第二个数组进行操作,每次用第一个数组给第二个数组初始化
- 用h表示该房子的下标,循环中的判断条件z<=h+k-1是因为该下标z也被操作了,所以要减去1,否则操作范围会有误(或者这样写也可以z<h+k),由于++h,每重循环都对下标加了1,所以下一次操作的房子一定要是h+=k-1,进入下一次循环的时候会自动的加上步长就是(h+=k)
- 每次都将次数与mi作比较,最终输出最小的次数
下面是第二种代码:(个人认为这份代码要优于上面的)
#include <bits/stdc++.h>
using namespace std;
int main() {int t; cin >> t;for (int i = 0, n, k; i < t; ++i) {cin >> n >> k;vector<int> arr(n);unordered_set<int> s;for (int j = 0; j < n; ++j) {cin >> arr[j];s.insert(arr[j]); //一个集合,防止重复记录}int ans = INT_MAX;for(auto &x : s) {int cnt = 0;for(int j = 0; j < n; ++j) {if(arr[j] == x) continue; //如果当前颜色和我要涂的颜色一样,那么跳过cnt ++;j += k - 1; //否则将k区间内的颜色全部涂该种颜色,由于上面有++j,这里要-1}ans = min(ans, cnt); //记录最小的就是答案}cout << ans << endl;}return 0;
}
这份代码用vector和unordered_set容器做了存储,大体上思路与上一份代码是一致的,这份代码最大的亮点就在于利用了unordered_set容器不重复的特性,无需将60种颜色都遍历(只遍历出现的颜色即可),小亮点在于他使用continue,避免了对数据的操作,直接使用下标来完成了上面代码繁琐的循环