暑假集训 || 区间DP
区间DP
经典石子合并问题V1 复杂度 On3
int a[SZ], sum[SZ], f[SZ][SZ];
int main()
{
int n;
scanf("%d", &n);
for(int i = ; i <= n; i++)
{
scanf("%d", &a[i]);
sum[i] = sum[i-] + a[i];
}
for(int len = ; len <= n; len++)
{
for(int l = ; l <= n-len+; l++)
{
int r = l+len-;
int ans = INF;
for(int k = l; k < r; k++)
ans = min(ans, f[l][k] + f[k+][r] + sum[r] - sum[l-]);
f[l][r] = ans;
}
}
printf("%d\n", f[][n]);
return ;
}
V2 复杂度 On2
环形问题可以在后面再接一段数组
int main()
{
int n;
scanf("%d", &n);
for(int i = ; i <= n; i++)
{
scanf("%d", &a[i]);
sum[i] = sum[i-] + a[i];
a[i+n] = a[i];
}
for(int i = n+; i <= *n; i++) sum[i] = sum[i-] + a[i];
for(int i = ; i <= *n; i++)
for(int j = ; j <= *n; j++)
{
if(i == j) f[i][j] = , s[i][j] = i;
else f[i][j] = INF;
}
for(int len = ; len <= n; len++)
{
for(int l = ; l <= *n-len+; l++)
{
int r = l+len-;
for(int k = s[l][r-]; k <= s[l+][r]; k++)
{
int ans = f[l][k] + f[k+][r] + sum[r] - sum[l-];
if(ans < f[l][r])
{
f[l][r] = ans;
s[l][r] = k;
}
}
}
}
int res = INF;
for(int i = ; i <= n; i++)
res = min(res, f[i][i+n-]);
printf("%d\n", res);
return ;
}
V3 复杂度 Onlogn
HDU 3516
给一堆点,在平面内选择一个位置做根,只能向右和向上连向点,问最小的连线总长度
竟然。。是区间DP问题。。。还要四边形优化
发现把两段合并好的树l~k-1 k~r 再合并在一起需要花费cal
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int SZ = ;
const int INF = 1e9+;
int a[SZ], sum[SZ], f[SZ][SZ], s[SZ][SZ];
struct node
{
int x, y;
}pos[SZ];
int cal(int l, int k, int r)
{
int ans = pos[k].x-pos[l].x + pos[k-].y-pos[r].y;
return ans;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = ; i <= n; i++) scanf("%d %d", &pos[i].x, &pos[i].y);
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
{
if(i == j) f[i][j] = , s[i][j] = i;
else f[i][j] = INF;
}
for(int len = ; len <= n; len++)
{
for(int l = ; l <= n-len+; l++)
{
int r = l+len-;
for(int k = s[l][r-]; k <= s[l+][r]; k++)
{
int ans = f[l][k-] + f[k][r] + cal(l, k, r);
if(ans <= f[l][r])
{
f[l][r] = ans;
s[l][r] = k;
}
}
}
}
printf("%d\n", f[][n]);
}
return ;
}
POJ 2955 括号匹配
为什么忘性这么大。。
int f[SZ][SZ], s[SZ][SZ];
int main()
{
char s[];
while()
{
scanf(" %s", s+);
if(s[] == 'e') break;
int n = strlen(s)-;
memset(f, , sizeof(f));
for(int len = ; len <= n; len++)
for(int l = ; l <= n-len+; l++)
{
int r = l+len-;
if((s[l] == '(' && s[r] == ')') || (s[l] == '[' && s[r] == ']')) f[l][r] = f[l+][r-]+;
for(int k = l; k < r; k++)
f[l][r] = max(f[l][r], f[l][k] + f[k+][r]);
}
printf("%d\n", f[][n]);
}
return ;
}
LightOJ 1422
题意:每一场Party都要穿相应的衣服,一次可以套着穿多件,如果某两场Party衣服一样,同一件就可以接着用,脱下过的衣服就不能再穿了 ,现在要求最少穿的衣服。
思路: f[i][j] 表示 i-j天里需要的衣服数,考虑区间dp
在l - r天内,若a[l] == a[r] 则第r天可以不穿,f[l][r] = f[l][r-1]
否则第r天要穿,f[l][r] = f[l][r-1]+1
然后枚举l - r之间的k,若a[l] == a[k] 则第k天可以不换,f[l][r] = min(f[l][r], f[l][k-1] + f[k][r])
区间DP的边界问题真的是个玄学orz
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int SZ = ;
int a[SZ], f[SZ][SZ];
int main()
{
int T, tt = ;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
for(int i = ; i <= n; i++)
scanf("%d", &a[i]);
memset(f, , sizeof(f));
for(int i = ; i <= n; i++) f[i][i] = ;
for(int len = ; len <= n; len++)
for(int l = ; l <= n; l++)
{
int r = l+len;
if(r > n) break;
if(a[l] == a[r]) f[l][r] = f[l][r-];
else f[l][r] = f[l][r-] + ;
for(int k = l+; k < r-; k++)
if(a[l] == a[k])
f[l][r] = min(f[l][r], f[l][k-] + f[k][r]);
}
printf("Case %d: %d\n", ++tt, f[][n]);
}
return ;
}
暑假集训 || 区间DP的更多相关文章
- [暑假集训--数位dp]hdu2089 不要62
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍, ...
- [暑假集训--数位dp]LightOj1205 Palindromic Numbers
A palindromic number or numeral palindrome is a 'symmetrical' number like 16461 that remains the sam ...
- [暑假集训--数位dp]hdu3709 Balanced Number
A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. ...
- [暑假集训--数位dp]hdu3555 Bomb
The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the ti ...
- [暑假集训--数位dp]hdu3652 B-number
A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- ...
- 暑假集训 || 概率DP
Codeforces 148D 考虑状态转移..https://www.cnblogs.com/kuangbin/archive/2012/10/04/2711184.html题意:原来袋子里有w只白 ...
- 暑假集训 || 树DP
树上DP通常用到dfs https://www.cnblogs.com/mhpp/p/6628548.html POJ 2342 相邻两点不能同时被选 经典题 f[0][u]表示不选u的情况数,此时v ...
- 2018.8.17 2018暑假集训 关于dp的一些感想(以目前的知识水平)
学了这么长时间的dp似乎还是不怎么样 谨以此篇文字记录一年以来与dp斗智斗勇的各种经历 关于dp(也就是动态规划)似乎对于每个OIer来说都是一个永远的噩梦. 刚刚开始学dp的时候完全搞不明白(只是觉 ...
- [暑假集训--数位dp]hdu5787 K-wolf Number
Alice thinks an integer x is a K-wolf number, if every K adjacent digits in decimal representation o ...
随机推荐
- 6-6 Haar特征3
B区域是包含AB这样两部分的.C区域是包含A和C这样两部分的.B区域和C区域它描述的是一个横条和一个竖条.D区域是四个方块之和. #haar 1 什么是haar? 特征 = 像素 运算 ->结果 ...
- ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 09. Model验证
数据注解 这样前后就会有div把这个inoput给包起来 添加一个Label使用TagHelper也有只能提示 出现的效果是这样的,实际上是把model的属性名打印出来.了. 把其他几个label也添 ...
- 51nod 1574 排列转换(猜结论)
分析 猜了一下结论,居然对了..........具体操作是:假设排列s是1,2,3,...,nk为排列p中最大的 没有放到正确位置的数,k的位置为posk的右边一定有一个数x<=pos(因为&l ...
- hdoj5301
题意: 有一个n*m的大矩阵, 其中有一个1*1的不要的位置(x,y), 然后用若干个小矩阵去覆盖大矩阵, 不要的不能被覆盖. 问小矩阵中面积最大的面积最小是多少. 思路: 巨巨先画一个矩形,看看那个 ...
- rpm -e ** error :No such file or directory 解决
参考文章:http://www.redhat.com/archives/rpm-list/2006-June/msg00025.html 我遇到的情况是这样的: 1 先安装包 rpm -ivh tes ...
- Luogu P1417烹调方案【dp/背包】By cellur925
题目传送门 我们看到这道题,就会想起背包.于是我就一顿01背包敲,结果发现只有30分.后来看题解发现需要对输入的食材进行排序. 我们回想国王游戏一题,各位大臣的排列顺序会对权值造成影响,所以我们就预先 ...
- 我的spring-boot开发环境
我的spring-boot开发环境,目的方便我快速搭建开发环境,同时可以最佳实践.使用spring-boot 2.1.x. 代码地址:GitHub my-springboot-examples 目的是 ...
- Linux下tcp服务器创建的步骤
创建一个socket,使用函数socket() socket(套接字)实质上提供了进程通信的端点,进程通信之前,双方首先必须建立各自的一个端点,否则没有办法通信.通过socket将IP地址和端口绑定之 ...
- iOS 加载Viewcontroller的几种方法
// 一.根据StoryboardID(需要在Storyboard设置),通过ViewController所在的Storyboard来加载: UIStoryboard *storyboard = [U ...
- AtCoder Regular Contest 062 E - AtCoDeerくんと立方体づくり / Building Cubes with AtCoDeer
题目传送门:https://arc062.contest.atcoder.jp/tasks/arc062_c 题目大意: 给你\(N\)块正方形木板,每块木板四角有四种颜色(可以相同),木板中央有编号 ...