【题解】P4749 [CERC2017]Kitchen Knobs
题目描述
你正一家大型的快餐餐厅的巨型灶台上烹饪。这个灶台上有n个炉子排成一排,并按序标为1-n号。每个炉子都会被它的控制手柄所控制。这些手柄可不一般:每个手柄上面都有1-7的号码围成一圈。灶台的火力就是从它的控制手柄顶端开始顺时针读取数字而得到的。
每一步你都可转动一个或多个相邻手柄——向任意方向转动任意几下。但是,同一步转动的手柄只能向同一方向转动同样的次数。
找到最少的步数来吧所有的炉子都设定到可能的最大火力。
输入输出格式
输入格式
第一行包含一个整数(1<=n<=501)表示炉子的数量。接下去第j行包含7个非零整数,其中第一个是初始火力大小。
输出格式
输出一个整数,表示需要的步数。
题解
个人觉得非常好的一道步步优化的DP题。
首先可以知道每个炉子需要多少步到最优解(全部相同的炉子舍弃掉)
这个东西区间似乎不太好做,那么我们来差分一下,而后一次操作相当与两个位置一加一减相同的数,目标是将所有数变成0。
现在有6种数,直接DP是。
首先可以小贪心一下,在意义下进行,将1和6,2和5,3和4先配对,于是现在只剩3种数,复杂度。
完结撒花!!❀❀❀
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
int f=1,j=0;
char w=getchar();
while(!isdigit(w)){
if(w=='-')f=-1;
w=getchar();
}
while(isdigit(w)){
j=j*10+w-'0';
w=getchar();
}
return f*j;
}
const int N=510;
short f[N][N][N];
int n,a[N][9],mx[N],p[7];
int ans,v[4],w[4];
signed main(){
n=rd();
for(int i=1;i<=n;i++){
a[i][1]=rd();
if(a[i][1]%1111111==0){
i--,n--;
continue;
}
for(int j=2;j<=7;j++)a[i][j]=(a[i][j-1]%1000000)*10+a[i][j-1]/1000000;
for(int j=1;j<=7;j++)if(a[i][mx[i]]<a[i][j])mx[i]=j;
mx[i]--;
// for(int j=1;j<=7;j++)cout<<a[i][j]<<" ";
// cout<<"\n";
}
for(int i=1;i<=n;i++)p[(mx[i]-mx[i-1]+7)%7]++;
// for(int i=1;i<=n;i++)cout<<mx[i]<<" ";
// cout<<"\n";
v[1]=(p[1]>p[6])?1:6,w[1]=abs(p[1]-p[6]);
v[2]=(p[2]>p[5])?2:5,w[2]=abs(p[2]-p[5]);
v[3]=(p[3]>p[4])?3:4,w[3]=abs(p[3]-p[4]);
ans=max(p[1],p[6])+max(p[2],p[5])+max(p[3],p[4]);
for(int i=0;i<=w[1];i++){
for(int j=0;j<=w[2];j++){
for(int k=0;k<=w[3];k++){
f[i][j][k]+=((i*v[1]+j*v[2]+k*v[3])%7==0);
f[i+1][j][k]=max(f[i+1][j][k],f[i][j][k]);
f[i][j+1][k]=max(f[i][j+1][k],f[i][j][k]);
f[i][j][k+1]=max(f[i][j][k+1],f[i][j][k]);
}
}
}
printf("%d\n",ans+1-f[w[1]][w[2]][w[3]]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】