1 条题解
-
0
自动搬运
来自洛谷,原作者为

弦巻こころ
放置型音游玩家搬运于
2025-08-24 22:03:13,当前版本为作者最后更新于2021-05-21 21:00:47,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
一道比较巧妙的思维题.
转化后题意:给你一个数组,每次可以将变成.求使得整个数组变为的最小操作次数.
这个题一看就非常差分,所以我们先差分一下.发现操作变成了,对于差分数组你可以将或者只将.
就相当于我们将所有分组,使得同一组的(这样同一组就可以用此组全部弄成)并且组数尽可能多.
乍一看好像没啥特别的,但是我们发现是不用操作的,,两两配对分组是很优秀的.而且配对过后,我们就只剩下3种数了.
我们此时将剩下的数设一个四维 表示,选了个第一种数,个第二种数,个第三种数,我们发现当时,我们此时组数就可以加一,因为我们此时必然可以通过的一些组合凑出一组新的为,转移就是你枚举一个数添加就行了.但的空间太大了开不下,我们可以滚动数组或者
short解决问题.注意你转化的时候,如果那个数字全部相同,那它是没有意义的(咋转都没区别),一定要记得特判这种情况!!!(考场上感觉很难想到这种情况)
转化就是你枚举一下顺时针转几次得到最大值,那个次数就是题目中的了
代码
#include<bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i=(j);i<=(k);i++) const int N=514; int n,nw,as,mx[N],a[N][8],p[10],c[10],ct[10]; short f[N][N][N]; void MX(short &a,short b){a=a>b?a:b;} int main(){ scanf("%d",&n); rep(i,1,n){scanf("%d",&a[i][0]); if(a[i][0]%1111111==0){i--;n--;continue;}//一定要判,巨坑 rep(j,1,6){ a[i][j]=(a[i][j-1]%1000000)*10+a[i][j-1]/1000000; if(a[i][mx[i]]<a[i][j])mx[i]=j; } }//转化mx[i]相当于a[i] rep(i,1,n)ct[(mx[i]-mx[i-1]+7)%7]++; p[1]=abs(ct[1]-ct[6]);c[1]=ct[1]>ct[6]?1:6; p[2]=abs(ct[2]-ct[5]);c[2]=ct[2]>ct[5]?2:5; p[3]=abs(ct[3]-ct[4]);c[3]=ct[3]>ct[4]?3:4;//将16,25,34先行配对,0不用管 as+=max(ct[1],ct[6])+max(ct[2],ct[5])+max(ct[3],ct[4]); rep(i,0,p[1])rep(j,0,p[2])rep(k,0,p[3]){ f[i][j][k]+=(i*c[1]+j*c[2]+k*c[3])%7==0;//这样就可以形成一个新的分组 MX(f[i+1][j][k],f[i][j][k]); MX(f[i][j+1][k],f[i][j][k]); MX(f[i][j][k+1],f[i][j][k]);//依次枚举数添加 } printf("%d",as+1-f[p[1]][p[2]][p[3]]); }
- 1
信息
- ID
- 3745
- 时间
- 3000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者