DP初步-
女生赛的糖果屋-
啊-简单递推-
这个地方建不建教室,要保证每一步都是最佳的话,也是要根据前面的来决定
状态的临界点是最开始那个房子肯定要建的,然后dp[i][0]是不建,dp[i][1]是建
那么,dn里面记录的 是这里面最佳的
也就是
不建 dp[i][0]=min(dp[i][0]+d[i][1])
建了 dp[i][1]=min(dp[i-1][0]+d[i-1][1])+ci;
(直接拦腰截断就好了...这里建了,前面那个没建/前面那个建了都无所谓,我只想要最大的就可以了)
然后再去讨论此处不建,此处不建何处建?从后往前找吧,把所有可有建的地方都枚举一遍好了
怎么枚举呢?j从大到小一点一点减少
然后就是,dp[j][1]加上后面从j开始到i中间的和
然后就是里面有个小点:
如果在j建立了,i没建立,然后他们之间的区间和?是多少
枚举...前面是在i处开始,后面是第j处见了教室
然后
t += (i - j) * (nodes[j+1].x - nodes[j].x)
也就是3建了,1和2都没建
比如我们要算x3 - x1 , x2 - x1的sum,那么由于保证了x是升序排列的,所以sum = (x3 - x2) + 2 * (x2 - x1).
也是(x3-x1)+ x2-x1=
x3-x2+x2+x2-x1-x1;
也就是,想拿到x3到x2中间的一段,和x2到
x1中间的一段
直接把所有的S存起来,然后S3-S2,S2-S1,
但是更麻烦一点的话,
【1 2 3 】
获得的是S1 S2 S3
2-3: 3.x-2.x 有几个呢?是i-j i是最终的嘛
1-3 后面算了两次...因为是i-j
再2加上 2.x-1.x(因为,这个是s3-s1加上s2-s1)
(也就是,s3=(s3-s2)+(s2-s1))
后面其实递推的话都是这样的= =...
然后就是,t+=(i-j)(j+1- j )
一直到前面j没了....
那好吧,最后还有一个边界的问题
啊啊啊,动态规划问题
【还有个一点点的小坑就是数据可能不是那么给的,所以要排序首先】
【还有就是要到最后一个...比如说你从0开始的就要到j>=0,1就是j>0】
【还有就是,1e5的话用ll.. 用ll啊】
而且别的都要用ll!!否则转换的时候出了问题还是会报错
好的吧,0416应该搞好的东西今天都已经0420了,为什么我写题的时间越来越少四月份都快过去了博客也几乎没写什么,还真的是 四月是你的春天啊= =...
女生赛的糖果屋-
啊-简单递推-
这第一步还是要自己迈出去的吧= =
(上代码)
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 3010;
typedef long long ll;
struct node {
ll x;
ll c;
}p[maxn];
bool cmp(node a, node b) {
return a.x < b.x;
//从小到大 可以的哦!
}
int main() {
int t; while (cin >> t) {
for (int i = 1; i <= t; i++)
{
cin >> p[i].x >> p[i].c;
}
sort(p + 1, p + 1 + t, cmp);
//....???要sort
ll dp[maxn][2];// = { 0 };
dp[1][1] = p[1].c;
dp[1][0] = 1e13-1;
for (int i = 2; i <= t; i++)
{
dp[i][0] = 1e13-1;
dp[i][1] = min(dp[i - 1][0], dp[i - 1][1]) + p[i].c;
//如果j=i的话,他们相等,然后呢
//哦....他是想说,在i之前建教室啊,这个j所以因此要从i-1枚举到1(边界)
//.... 但是如果你建教室的话,之前的所有可能就却都被砍死了!(认真!)
ll k = 0;
for (int j = i - 1; j > 0; j--)
{
//这之后 是从后往前枚举了
k = k + (p[j + 1].x - p[j].x)*(i - j);
//然后每次加上的是 p[j].x-p[j-1]x *(j-i) 也就是重复了几遍!
//没错!然后就 是这个可以再写一遍!
dp[i][0] = min(dp[i][0], dp[j][1] + k);
//就是在这个位置不建的话...
//...这个只是用来记录的而已吧!!!
//只是每次都罗列一下然后取到了最小值...另外新写一个也可以
//也就是前面那么多,在哪里新建最划算 ,...可以承受住 o(n2)的算法!
}
}
ll ans = min(dp[t][0], dp[t][1]);
cout << ans << endl;
}
return 0;
}
这个地方建不建教室,要保证每一步都是最佳的话,也是要根据前面的来决定
状态的临界点是最开始那个房子肯定要建的,然后dp[i][0]是不建,dp[i][1]是建
那么,dn里面记录的 是这里面最佳的
也就是
不建 dp[i][0]=min(dp[i][0]+d[i][1])
建了 dp[i][1]=min(dp[i-1][0]+d[i-1][1])+ci;
(直接拦腰截断就好了...这里建了,前面那个没建/前面那个建了都无所谓,我只想要最大的就可以了)
然后再去讨论此处不建,此处不建何处建?从后往前找吧,把所有可有建的地方都枚举一遍好了
怎么枚举呢?j从大到小一点一点减少
然后就是,dp[j][1]加上后面从j开始到i中间的和
然后就是里面有个小点:
如果在j建立了,i没建立,然后他们之间的区间和?是多少
枚举...前面是在i处开始,后面是第j处见了教室
然后
t += (i - j) * (nodes[j+1].x - nodes[j].x)
也就是3建了,1和2都没建
比如我们要算x3 - x1 , x2 - x1的sum,那么由于保证了x是升序排列的,所以sum = (x3 - x2) + 2 * (x2 - x1).
也是(x3-x1)+ x2-x1=
x3-x2+x2+x2-x1-x1;
也就是,想拿到x3到x2中间的一段,和x2到
x1中间的一段
直接把所有的S存起来,然后S3-S2,S2-S1,
但是更麻烦一点的话,
【1 2 3 】
获得的是S1 S2 S3
2-3: 3.x-2.x 有几个呢?是i-j i是最终的嘛
1-3 后面算了两次...因为是i-j
再2加上 2.x-1.x(因为,这个是s3-s1加上s2-s1)
(也就是,s3=(s3-s2)+(s2-s1))
后面其实递推的话都是这样的= =...
然后就是,t+=(i-j)(j+1- j )
一直到前面j没了....
那好吧,最后还有一个边界的问题
啊啊啊,动态规划问题
【还有个一点点的小坑就是数据可能不是那么给的,所以要排序首先】
【还有就是要到最后一个...比如说你从0开始的就要到j>=0,1就是j>0】
【还有就是,1e5的话用ll.. 用ll啊】
而且别的都要用ll!!否则转换的时候出了问题还是会报错
好的吧,0416应该搞好的东西今天都已经0420了,为什么我写题的时间越来越少四月份都快过去了博客也几乎没写什么,还真的是 四月是你的春天啊= =...