I - Necklace

FZU - 2302

题目大意:给出一个环每一段的价值为区间和的平方,求将环断成k断的最小价值之和。

解题思路:容易想到n^4的dp

首先断环成链,将数组复制一遍。

用dp[i][j]表示前i个分成j断的最小代价,那么我们就枚举区间,枚举段数,没增加一个点,当前点要么独立成一段,要么跟前边的成一段,所以再枚举间断点。

由于起点不确定,所以我们要做n次的dp,时间复杂度为n^4

这个是超时的代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<ctime>
#include<map>
#include<set>
#include<algorithm>
#include<vector>
using namespace std;
#define LL long long
#define N 5000005
#define maxn 10005
#define inf 0x3f3f3f3f
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)LL a[405],b[405];
LL sum[405];
LL dp[405][405];LL Sum(int l,int r)
{if(l>r) return 0;return (sum[r]-sum[l-1])*(sum[r]-sum[l-1]);
}LL solve(int n,int k)
{for(int i=1;i<=n;i++){for(int j=1;j<=k;j++)dp[i][j]=inf;}for(int i=1;i<=n;i++)dp[i][0]=0;for(int i=1; i<=n; i++){for(int j=1; j<=k; j++){if(i<j)continue;if(j==1)dp[i][j]=Sum(1,i);elsefor(int l=i; l>=j-1; l--){dp[i][j]=min(dp[i][j],dp[l][j-1]+Sum(l+1,i));}//cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;}}return dp[n][k];
}int main()
{int t;sca(t);while(t--){int n,k;scanf("%d%d",&n,&k);sum[0]=0;for(int i=1; i<=n; i++)scanf("%lld",&a[i]),a[n+i]=a[i];LL ans=inf;for(int i=1; i<=n; i++){int cnt=1;sum[0]=0;for(int j=i; j<=i+n-1; j++){b[cnt]=a[j];sum[cnt]=sum[cnt-1]+a[j];cnt++;}ans=min(ans,solve(n,k));}printf("%lld\n",ans);}
}

当时只是知道可以优化但是不知道怎么去优化。后来学习一斜率优化。

首先我们知道

前i个分成j段

Sum(l,r)=(sum[r]-sum[l])*(sum[r]-sum[l]);

即dp[i][j]=dp[l][j-1]+Sum(l,r)^2  (l>=0 && r<i)

其中dp[i][j]要取最小值

展开 dp[i][j]=dp[l][j-1]+sum[r]^2+sum[l]^2-2*sum[r]sum[l]

移项 dp[i][j]+2*sum[r]sum[l]=sum[l][j-1]+sum[r]^2+sum[l]^2;

这个式子可以看做是   b+kx=y

因为2sum[r]为常数,可以看做是当前的斜率。sum[l]使我们要枚举的x点 sum[l][j-1]是我们在上层循环已经求过的值

可以看做是y点(sum[r]^2是一个常数,在求斜率的时候相减就抵消了,所以两边都是单变量)。

此时我们要求的dp[i][j]就是x=0时的截距。

我们希望截距尽量小。

所以维护一个下凸包。

如图所示,当我去找使刚才那个式子的截距最小的点对的时候,我们发现

若果当前队列中的前两个点的斜率小于当前的斜率,那么A点就可以不要了。因为在B点可以取得更优的值。

同理我们将队列前边的不符合要求的点都去掉,取得最优值。

然后我们要将现在的点加入,加入的时候也是同理,我们比较当前队列尾部的两个点的斜率和当前斜率(对于本题来说是2*sum[i])的关系,如果斜率大于当前斜率,我们发现C点也可以去掉了。

就这样不断去除两端的点,就得到了优化。

可以优化到n^3。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<ctime>
#include<map>
#include<set>
#include<algorithm>
#include<vector>
using namespace std;
#define N 5000005
#define maxn 10005
#define inf 0x3f3f3f3f
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)int  a[405],b[405];
int  sum[405];
int  dp[205][205];
int q[1005];int  Sum(int l,int r)
{if(l>r) return 0;return (sum[r]-sum[l])*(sum[r]-sum[l]);
}int  X(int x,int y)
{return 2*(sum[x]-sum[y]);
}int  Y(int x,int y,int k)
{return (dp[x][k]+sum[x]*sum[x])-( dp[y][k]+sum[y]*sum[y]);
}int  solve(int n,int k)
{for(int i=1;i<=n;i++){for(int j=1;j<=k;j++)dp[i][j]=inf;}for(int i=1;i<=n;i++)dp[i][1]=Sum(0,i);int head=0,tail=0;for(int i=2;i<=k;i++){head=tail=0;q[tail++]=i-1;for(int j=i;j<=n;j++){while(head+1<tail &&Y(q[head+1],q[head],i-1)<=sum[j]*X(q[head+1],q[head]) )head++;dp[j][i]=dp[q[head]][i-1]+Sum(q[head],j);while(head+1<tail &&Y(q[tail-1],q[tail-2],i-1)*X(j,q[tail-1])>=Y(j,q[tail-1],i-1)*X(q[tail-1],q[tail-2]))tail--;q[tail++]=j;}}return dp[n][k];
}int main()
{//freopen("D:\in.txt", "r", stdin);//freopen("D:\ougly.txt","w",stdout);int t;sca(t);while(t--){int n,k;scanf("%d%d",&n,&k);for(int i=1; i<=n; i++)scanf("%d",&a[i]),a[n+i]=a[i];int  ans=inf;for(int i=1; i<=n; i++){int cnt=1;sum[0]=0;for(int j=i; j<=i+n-1; j++){b[cnt]=a[j];sum[cnt]=sum[cnt-1]+a[j];cnt++;}ans=min(ans,solve(n,k));}printf("%d\n",ans);}
}/**/

FZU - 2302  Necklace (dp+斜率优化)相关推荐

  1. BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )

    既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...

  2. BZOJ 3156: 防御准备( dp + 斜率优化 )

    dp(i)表示处理完[i,n]且i是放守卫塔的最小费用. dp(i) = min{dp(j) + (j-i)(j-i-1)/2}+costi(i<j≤N) 然后斜率优化 ------------ ...

  3. 【BZOJ-3156】防御准备 DP + 斜率优化

    3156: 防御准备 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 951  Solved: 446 [Submit][Status][Discus ...

  4. [HNOI2008]玩具装箱toy(dp+斜率优化)

    斜率优化问题一般都是决策单调问题.对于这题能够证明单调决策. 令sum[i]=sigma(c [k] ) 1<=k<=i  ,  f[i]=sum[i]+i ,  c=L+1; 首先我们能 ...

  5. UVAlive 6131 dp+斜率优化

    这道题和06年论文<从一类单调性问题看算法的优化>第一道例题很相似. 题意:给出n个矿的重量和位置,这些矿石只能从上往下运送,现在要在这些地方建造m个heap,要使得,sigma距离*重量 ...

  6. hdu 3507 Print Article(dp+斜率优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507 题解:显然这题的递推很容易得到 dp[i]=dp[j]+(sum[i]-sum[j])^2+m ...

  7. C++剑指offer:解题报告之DP优化学习记 (二) ——浅论DP斜率优化 (Print Article 【HDU - 3507】 )

    链接:https://share.weiyun.com/5LzbzAc 目录 前言 斜率优化前期准备 1.从状态转移方程出发 2.推理状态转移方程 对结论的进一步推导 干货!综合结论 判断斜率大小的方 ...

  8. P3994 高速公路 树形DP+斜率优化+二分

    $ \color{#0066ff}{ 题目描述 }$ C国拥有一张四通八达的高速公路网树,其中有n个城市,城市之间由一共n-1条高速公路连接.除了首都1号城市,每个城市都有一家本地的客运公司,可以发车 ...

  9. CDOJ 879 摩天轮 dp+斜率优化

    原题链接:http://www.acm.uestc.edu.cn/#/problem/show/879 题意: 中文题 题解: 这是一道斜率dp的题. 先把$a$数组排个序. 令$dp[i][j]$表 ...

最新文章

  1. 【IT笔试面试题整理】字符串的排列
  2. 记录一次webpack3升级到webpack4过程
  3. 共享没有权限访问权限_如何与家人共享SmartThings访问权限
  4. 【CF1189F】Array Beauty【dp】【复杂度玄学优化】
  5. Python-jieba分词学习及应用
  6. 前端校验和后端校验区别
  7. Linux笔记-centos中大量tcp状态为TIME_WAIT
  8. 3G手机Android应用开发视频教程_黎活明老师的视频(第三天课程)总共有八天课程...
  9. 云小课 | 需求任务还未分解,该咋整!项目管理Scrum项目工作分解的心酸谁能知?
  10. vs2015编译ffmpeg
  11. 华为诺亚方舟 | 构建1亿组图文对中文多模态数据集
  12. 火狐 firefox proxy moz=proxy:// 407错误 解决办法
  13. 电脑开机太慢?这5个方法瞬间提升你的电脑速度
  14. cesium 粒子特效
  15. 在外包干了几年,感觉自己都快费了
  16. [electron]Electron安装报错connect ETIMEDOUT
  17. 九连环的递归实现,以及数列通项
  18. ROS2报错缺少“diagnostic_updater“,CMake did not find diagnostic_updater. 解决思路
  19. 计算机将文本朗读出来应用语音,如何实现电脑语音朗读文字?可以选择两种方法...
  20. Workspace Cannot Be Created

热门文章

  1. 联璧爆雷?斐讯要甩锅?别听信谣言,一起捋捋这个事
  2. 英语记忆软件测试大乐,‎App Store 上的“学习土耳其词汇 - 学英语法游戏单词汇记忆卡片小测试练习”...
  3. MySQL--MHA高可用配置及故障切换实例
  4. python smtplib.SMTP()发送邮件报“UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xba in position 0: i
  5. 443 k8s配置开启nginx_k8s部署nginx集群
  6. Bitmap 和 File 相互转换
  7. 海波龙(Oracle Hyperion)单点登陆问题记录
  8. System.getenv(name)获取不到环境变量在Idea中
  9. 诺基亚安卓手机_用诺基亚那个年代玩的Java游戏,现在终于能用安卓手机玩了...
  10. 高通手机型号、开机logo、默认语言设置等小修改