FZU - 2302 Necklace (dp+斜率优化)
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+斜率优化)相关推荐
- BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )
既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...
- BZOJ 3156: 防御准备( dp + 斜率优化 )
dp(i)表示处理完[i,n]且i是放守卫塔的最小费用. dp(i) = min{dp(j) + (j-i)(j-i-1)/2}+costi(i<j≤N) 然后斜率优化 ------------ ...
- 【BZOJ-3156】防御准备 DP + 斜率优化
3156: 防御准备 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 951 Solved: 446 [Submit][Status][Discus ...
- [HNOI2008]玩具装箱toy(dp+斜率优化)
斜率优化问题一般都是决策单调问题.对于这题能够证明单调决策. 令sum[i]=sigma(c [k] ) 1<=k<=i , f[i]=sum[i]+i , c=L+1; 首先我们能 ...
- UVAlive 6131 dp+斜率优化
这道题和06年论文<从一类单调性问题看算法的优化>第一道例题很相似. 题意:给出n个矿的重量和位置,这些矿石只能从上往下运送,现在要在这些地方建造m个heap,要使得,sigma距离*重量 ...
- hdu 3507 Print Article(dp+斜率优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507 题解:显然这题的递推很容易得到 dp[i]=dp[j]+(sum[i]-sum[j])^2+m ...
- C++剑指offer:解题报告之DP优化学习记 (二) ——浅论DP斜率优化 (Print Article 【HDU - 3507】 )
链接:https://share.weiyun.com/5LzbzAc 目录 前言 斜率优化前期准备 1.从状态转移方程出发 2.推理状态转移方程 对结论的进一步推导 干货!综合结论 判断斜率大小的方 ...
- P3994 高速公路 树形DP+斜率优化+二分
$ \color{#0066ff}{ 题目描述 }$ C国拥有一张四通八达的高速公路网树,其中有n个城市,城市之间由一共n-1条高速公路连接.除了首都1号城市,每个城市都有一家本地的客运公司,可以发车 ...
- CDOJ 879 摩天轮 dp+斜率优化
原题链接:http://www.acm.uestc.edu.cn/#/problem/show/879 题意: 中文题 题解: 这是一道斜率dp的题. 先把$a$数组排个序. 令$dp[i][j]$表 ...
最新文章
- 【IT笔试面试题整理】字符串的排列
- 记录一次webpack3升级到webpack4过程
- 共享没有权限访问权限_如何与家人共享SmartThings访问权限
- 【CF1189F】Array Beauty【dp】【复杂度玄学优化】
- Python-jieba分词学习及应用
- 前端校验和后端校验区别
- Linux笔记-centos中大量tcp状态为TIME_WAIT
- 3G手机Android应用开发视频教程_黎活明老师的视频(第三天课程)总共有八天课程...
- 云小课 | 需求任务还未分解,该咋整!项目管理Scrum项目工作分解的心酸谁能知?
- vs2015编译ffmpeg
- 华为诺亚方舟 | 构建1亿组图文对中文多模态数据集
- 火狐 firefox proxy moz=proxy:// 407错误 解决办法
- 电脑开机太慢?这5个方法瞬间提升你的电脑速度
- cesium 粒子特效
- 在外包干了几年,感觉自己都快费了
- [electron]Electron安装报错connect ETIMEDOUT
- 九连环的递归实现,以及数列通项
- ROS2报错缺少“diagnostic_updater“,CMake did not find diagnostic_updater. 解决思路
- 计算机将文本朗读出来应用语音,如何实现电脑语音朗读文字?可以选择两种方法...
- Workspace Cannot Be Created
热门文章
- 联璧爆雷?斐讯要甩锅?别听信谣言,一起捋捋这个事
- 英语记忆软件测试大乐,App Store 上的“学习土耳其词汇 - 学英语法游戏单词汇记忆卡片小测试练习”...
- MySQL--MHA高可用配置及故障切换实例
- python smtplib.SMTP()发送邮件报“UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xba in position 0: i
- 443 k8s配置开启nginx_k8s部署nginx集群
- Bitmap 和 File 相互转换
- 海波龙(Oracle Hyperion)单点登陆问题记录
- System.getenv(name)获取不到环境变量在Idea中
- 诺基亚安卓手机_用诺基亚那个年代玩的Java游戏,现在终于能用安卓手机玩了...
- 高通手机型号、开机logo、默认语言设置等小修改