省選專練之 CERC2017 Kitchen Knobs 炸雞店
阿新 • • 發佈:2018-12-10
你正一家大型的快餐餐廳的巨型灶臺上烹飪。這個灶臺上有n個爐子排成一排,並按序標為1-n號。每個爐子都會被它的控制手柄所控制。這些手柄可不一般:每個手柄上面都有1-7的號碼圍成一圈。灶臺的火力就是從它的控制手柄頂端開始順時針讀取數字而得到的。
每一步你都可轉動一個或多個相鄰手柄——向任意方向轉動任意幾下。但是,同一步轉動的手柄只能向同一方向轉動同樣的次數。
找到最少的步數來吧所有的爐子都設定到可能的最大火力。
思維難題,也是這場比賽的金牌題
但你說考不能考到NOIP呢?也不是不行
這道題考察了泛化物品這個概念和差分的應用(這不都是NOIP知識點嗎)
第一發現只需要順時針轉動。(逆時針等於順時針+7)
此時問題轉化為了:對一段進行區間加和取膜(7)使這段區間變為全零。
似乎發現全零是單點的,所以考慮對序列差分
此時轉化為對差分序列進行單點修改是他變為全0
考慮配對1-6 2-5 3-4
這些東西為什麼是對的?
原因是1差分是-1+1而這使6變成7則合法了
然後剩下找最多的全零組。
一個加起來對7取mod的值為0的組稱之為全0組
// luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; const int N=1e5+100; typedef int INT; #define int short inline void up(int&a,int b){a>b?(a=b):0;} const int INF=1e4+7; inline int Get(char *S){ int l=0,r=1,len=0; while(l<7&&r<7&&len<7){ int t=S[(l+len)%7]-S[(r+len)%7]; if(t==0){ len++; } else{ if(t<0){ l+=(len+1); } else r+=(len+1); if(l==r)r++; len=0; } } int now=-1; for(int i=1;i<7;++i){ if(S[i]!=S[i-1])now=1; } if(now==-1)return now; return min(l,r); } char S[N]; int v[N]; int n; int cnt[7]; struct Node{ int a,b,c,v; }e[N]; int tot=0; int F[501][501][501]; int ans=0; int A,B,C; int x,y,z; INT main(){ // freopen("test.in","r",stdin); INT Cas; scanf("%d",&Cas); while(Cas--){ scanf("%s",S); int sum=Get(S); if(sum>=0)v[++n]=sum; } for(int i=n+1;i;--i)v[i]-=v[i-1]; for(int i=1;i<=n+1;++i)(v[i]=(v[i]+7)%7); n++; for(int i=1;i<=n;++i)++cnt[v[i]]; while(cnt[1]&&cnt[6])cnt[1]--,cnt[6]--,ans++; A=cnt[1]?cnt[1]:cnt[6]; x=cnt[1]?1:6; while(cnt[2]&&cnt[5])cnt[2]--,cnt[5]--,ans++; B=cnt[2]?cnt[2]:cnt[5]; y=cnt[2]?2:5; while(cnt[3]&&cnt[4])cnt[3]--,cnt[4]--,ans++; C=cnt[3]?cnt[3]:cnt[4]; z=cnt[3]?3:4; for(int i=0;i<=7;++i){ for(int j=0;j<=7;++j){ for(int k=0;k<=7;++k){ if(i+j+k&&(i*x+j*y+k*z)%7==0){ ++tot; e[tot].a=i; e[tot].b=j; e[tot].c=k; e[tot].v=i+j+k-1; } } } } for(int i=0;i<=A;++i){ for(int j=0;j<=B;++j){ for(int k=0;k<=C;++k){ if(i+j+k){ int sum=INF; for(int t=1;t<=tot;++t){ if(i>=e[t].a&&j>=e[t].b&&k>=e[t].c){ up(sum,F[i-e[t].a][j-e[t].b][k-e[t].c]+e[t].v); } } F[i][j][k]=sum; } } } } cout<<ans+F[A][B][C]; }