博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
11.03T1 DP
阅读量:5965 次
发布时间:2019-06-19

本文共 2426 字,大约阅读时间需要 8 分钟。

#3874 naive 的瓶子

 

描述

众所周知,小 naive 有 n 个瓶子,它们在桌子上排成一排。第 i 个瓶子的颜色为 ci,每个瓶子都有灵性,每次操作可以选择两个相邻的瓶子,消耗他们颜色的数值乘积的代价将其中一个瓶子的颜色变成另一个瓶子的颜色。

现在 naive 要让所以瓶子的颜色都一样,操作次数不限,但要使得操作的总代价最小。

输入

输入文件为 colour.in。

一个测试点内多组数据。

第一行,一个正整数 T,表示数据组数。 每组数据内:

第一行一个整数 n,为瓶子的个数。

第二行共 n 个整数,第 i 个整数为第 i 个瓶子的颜色 ci。

输出

输入文件为 colour.out。

共一行,一个整数,为最小的总代价。

样例输入[复制]
1
4
7 4 6 10
样例输出[复制]
92
提示

样例解释

{7 4 6 10}− > {4 4 6 10}− > {4 4 4 10}− > {4 4 4 4}。

总代价为 7 × 4 + 4 × 6 + 4 × 10 = 92。

【数据范围】

1 ≤ T ≤ 10。

n<=300,ci<=10^5

标签
ZYH
 
 
 
方法

测试点 1-8

naive 的瓶子 (colour)

记忆化搜索,把当前的状态用 vector<int> 表示,用 map<vetor<int>, long long> 记录到达 vector<int> 的最小总代价,O(n) 枚举转移。设 m = min(n, max{ai}),时间复杂度为O(mn× n × m × log2m)。

测试点 9-20

首先我们可以枚举最后的颜色 sc

可以发现,一个瓶子要么直接被染成目标颜色,要么先被染成数值比较小的颜色,再被染成目标颜色。也就是说一个瓶子颜色的数值最多变小一次。这个结论十分显然。首先我们肯定是把一些颜色不为目标颜色的数值比较大的瓶子染成数值比较小颜色,但要确保还存在目标颜色,再最后把所有其他颜色染成目标颜色。在第一步中,一个瓶子颜色的数值肯定不会变大, 此外,也不会变小两次,假设他变小了两次,那么我们完全可以直接变小成第二次,这样肯定不会变劣。

所以我们就可以动态规划了,设 fi为把前 i 个瓶子染成目标颜色的最小代价,每次转移选择接下来的一个区间,先把他们染成这个区间中数值最小的颜色,再染成目标颜色。

但需要注意的是,在第一步中不能把所有颜色都染成非目标颜色,那么我们可以类似 fi的再做一遍 gi,为把 [i, n] 染成目标颜色的最小代价。那么最后的答案为 min{

fi1+gi+1|ci= sc}

感觉这题的复杂度还可以优化,但是出题人太菜了。

 

 

 

code:

1 #include
2 #include
3 #include
4 #define N 1000 5 using namespace std; 6 long long a[N],Min[N][N],dp[N][N],vis[N],f[N]; 7 int main(){ 8 long long T; 9 cin>>T;10 while(T--){11 long long n;12 cin>>n;13 memset(a,0,sizeof a);14 memset(Min,0,sizeof Min);15 for(long long i=1;i<=n;i++)cin>>a[i];16 memset(dp,0,sizeof dp);17 for(long long i=1;i<=n;i++){18 Min[i][i]=a[i];19 dp[i][i]=0;20 for(long long j=i+1;j<=n;j++){21 Min[i][j]=min(Min[i][j-1],a[j]);22 for(long long k=i;k<=j;k++){23 if(a[k]==Min[i][j])continue;24 dp[i][j]+=Min[i][j]*a[k];//calc val25 }26 }27 }28 memset(vis,0,sizeof(vis));29 long long min0=9999999999999;30 for(long long i=1;i<=n;i++){
//枚举我要变成的值 31 if(vis[a[i]])continue;32 vis[a[i]]=1;33 long long now=a[i];34 memset(f,0x3f3f3f3f,sizeof f);35 f[0]=0;36 for(long long j=1;j<=n;j++){
//枚举我当前计算的f[j] 37 for(long long k=0;k

over

转载于:https://www.cnblogs.com/saionjisekai/p/9902149.html

你可能感兴趣的文章
如何给服务器设置邮件警报。
查看>>
CEF js调用C#封装类含注释
查看>>
麦克劳林
查看>>
Eclipse SVN修改用户名和密码
查看>>
架构师的职责都有哪些?
查看>>
SVN: bdb: BDB1538 Program version 5.3 doesn't match environment version 4.7
查看>>
jsp内置对象作业3-application用户注册
查看>>
android115 自定义控件
查看>>
iOS uuchart 用法
查看>>
c# 多线程 调用带参数函数
查看>>
JQuery 如何选择带有多个class的元素
查看>>
The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar
查看>>
VS快速生成JSON数据格式对应的实体
查看>>
Word2vec 模型载入(tensorflow)
查看>>
Linux内核——定时器和时间管理
查看>>
J2EE之初识JSP
查看>>
RabbitMq消息序列化简述
查看>>
i.e., e.g., etc.
查看>>
git忽略文件【转】
查看>>
Web上的支持的图片格式以及它们之间的区别
查看>>