[dp] Jzoj P5925 naive的瓶子
题解
- 颜色的数量很少,可以考虑枚举最后变成哪一种颜色
- 对于一个瓶子,可以发现它只有两种可能
- ①直接变成目标颜色
- ②变为一个较小的颜色,然后再变成目标颜色
- 设f[i]为前i个瓶子,都变成了目标颜色的最小代价
- 每次与后一个或前一个比较,如果当前先变成前一个或后一个再变成目标颜色比较优
- 这样的话就可以转移了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define inf 0x3f3f3f3f3f 5 using namespace std; 6 int n,t; 7 long long a[310],b[310],ans; 8 void work(long long x) 9 { 10 long long r=0,y=0; 11 memcpy(b,a,sizeof b); 12 for (int i=1;i<=n-1;i++) 13 if (b[i]!=x&&b[i+1]!=x&&b[i]>b[i+1]&&b[i]*b[i+1]+x*b[i+1]<x*b[i]) 14 r+=b[i]*b[i+1],b[i]=b[i+1]; 15 for (int i=2;i<=n;i++) 16 if (b[i]!=x&&b[i-1]!=x&&b[i]>b[i-1]&&b[i]*b[i-1]+x*b[i-1]<x*b[i]) 17 r+=b[i]*b[i-1],b[i]=b[i-1]; 18 for (int i=1;i<=n;i++) if (b[i]!=x) y+=b[i]; 19 ans=min(ans,x*y+r); 20 } 21 int main() 22 { 23 freopen("colour.in","r",stdin),freopen("colour.out","w",stdout); 24 scanf("%d",&t); 25 while (t--) 26 { 27 scanf("%d",&n),ans=inf; 28 for (int i=1;i<=n;i++) scanf("%lld",&a[i]); 29 for (int i=1;i<=n;i++) work(a[i]); 30 printf("%lld\n",ans); 31 } 32 }