Sue的小球

名次排序问题

方块消除

奥运物流

Sue的小球

题目大意

有 \(n\) 个小球在下落,初始位置 \((x_i,y_i)\),下落速度为 \(v_i\)。你初始位置在 \(x_0\),速度为 \(1\)。我们定义一个小球的贡献为接到它的时候它的纵坐标。问接到每个小球(接只接一次)的贡献之和的最大值。

\(n\le 10^3\)。

思路

算是为dp开了另外一种思路。

首先你发现,我们贪心一下,肯定每次选没选且最靠近当前位置的小球,具体证明不是很难。形式化一下,就是说按横坐标排序之后,假设已经接到 \(l\sim r\),那么下次一定接 \(l-1\) 或者 \(r+1\)。

于是,我们可以设 \(dp_{l,r,0/1}\) 表示接到 \(l\sim r\) 这段区间当前是在 \(l/r\) 时的小球的最大贡献。然后你发现这样很合理,但是你不好进行转移,因为你不能算出当前的时间。

但是转念一想,我们发现,如果我们能够在计算每个小球就把当前没有接到的小球消失的贡献都去掉的话就没有这种问题了。于是我们可以设 \(w_{l,r}=\sum_{i=1}^n v_i-\sum_{i=l}^{r}v_i\),那么我们可以得到转移式:

\[dp_{l,r,0}\to y_l+\max\{dp_{l+1,r,0}-w_{l+1,r}\times (x_{l+1}-x_l),dp_{l+1,r,1}-w_{l+1,r}\times (x_r-x_l)\}
\]

\(dp_{l,r,1}\) 同理。时间复杂度 \(\Theta(n^2)\)。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define MAXN 1005 struct node{
int x,y,v;
bool operator < (const node &p)const{return x < p.x;}
}fuck[MAXN]; int n,x0,w[MAXN][MAXN],f1[MAXN][MAXN],f2[MAXN][MAXN]; template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} int Abs (int x){return x > 0 ? x : -x;} signed main(){
read (n,x0);int tot = 0;
for (Int i = 1;i <= n;++ i) read (fuck[i].x);
for (Int i = 1;i <= n;++ i) read (fuck[i].y);
for (Int i = 1;i <= n;++ i) read (fuck[i].v),tot += fuck[i].v;
sort (fuck + 1,fuck + n + 1);
memset (f1,0xcf,sizeof (f1));
memset (f2,0xcf,sizeof (f2));
for (Int i = 1;i <= n;++ i)
for (Int j = i,sum = 0;j <= n;++ j) sum += fuck[j].v,w[i][j] = tot - sum;
for (Int i = 1;i <= n;++ i) f1[i][i] = f2[i][i] = fuck[i].y - Abs (x0 - fuck[i].x) * tot;
for (Int i = n;i >= 1;-- i)
for (Int j = i + 1;j <= n;++ j)
f1[i][j] = max (f1[i][j],fuck[i].y + f1[i + 1][j] - (fuck[i + 1].x - fuck[i].x) * w[i + 1][j]),
f1[i][j] = max (f1[i][j],fuck[i].y + f2[i + 1][j] - (fuck[j].x - fuck[i].x) * w[i + 1][j]),
f2[i][j] = max (f2[i][j],fuck[j].y + f1[i][j - 1] - (fuck[j].x - fuck[i].x) * w[i][j - 1]),
f2[i][j] = max (f2[i][j],fuck[j].y + f2[i][j - 1] - (fuck[j].x - fuck[j - 1].x) * w[i][j - 1]);
printf ("%.3f\n",max (f1[1][n],f2[1][n]) / 1000.0);
return 0;
}

名次排序问题

题目大意

给出一个 \(n\) 个点的序列 \(a_{1,2,...,n}\),每次可以把 \(i\) 换到 \(j\),贡献是 \(i+j\) ,问最后变成一个单调下降序列的最小贡献时的交换次数。

\(n\le 10^3\),保证 \(a_i\) 互不相等。

思路

论文

luogu上没有,如果有的话一定是个黑题吧。

首先我们可以转移题意,转换成一个权值 \(\in [1,n]\) 的序列,变为 \(1\sim n\) 的最小贡献。

然后你发现这个东西有以下 \(2\) 个性质:

  • 每个点只会交换一次

  • 交换一定权值从大到小进行

第一个显然,第二个可以靠猜(反正我猜中了)或者感性理解。

于是我们得到一个几个推论:

  1. 对于每一个数 \(x\),你在移动时有两种选择,1、 移动到数 \(x+1\) 前面,或者如果 \(x\) 的位置小于 \(x+1\) 的位置,那么可以不移动,等待后面 \(x\) 到 \(x+1\) 之间的数都移动走。

  2. 对于每一个数 \(x\),比它小的数相对位置不变。(相对位置就是指谁在前谁在后)

  3. 对于每一个数 \(x\),比 \(x+1\) 大的数都一定在 \(x+1\) 后面。

后面 2 个推论可以从第 1 个推出来,这里就不讲了。(因为跟主旨无关(是不是该夸夸我详略得当(伦敦雾

但是我们发现我们光知道相对位置没有什么用啊,我们得知道确切位置才可以啊。其实知道相对位置是做得到的。

我们发现对于一个数 \(x\) ,如果 \(x+1\sim n\) 都移动完了,那么当前位置其实就是 \(1\sim pos_x\) 中比 \(x\) 小的数 \(+1\) ,其中 \(pos_x\) 就是 \(x\) 在原序列的位置。这个可以从推论 2 看出来。

然后你发现还是不好搞,于是我们修改一下规则,把移动 \(i\to j\) 变为 \(i\) 加入 \(j\) 所在的点。然后你发现这样做的话,你就不会移动点了,而且点之间的相对位置也不会改变。(具体例子可以看论文)

接着我们设 \(c(p,x)\) 表示原序列中 \(1\sim p\) 中比 \(x\) 小的数 \(+1\)。然后我们发现如果 \(pos_i<j\) ,把 \(i\) 移动到 \(j\) 的贡献其实就是 \(c(pos_i,i)+c(j,i+1)-1\)(\(-1\) 是因为移动到 \(j-1\) 前面)。\(pos_i>j\) 同理。

于是我们考虑设 \(dp_{i,j}\) 表示已经考虑了 \(i+1\sim n\),且点 \(i\) 移动到 \(j\) 的最小贡献。对于第1中选择,转移式就是:

\[dp_{i,j}=dp_{i+1,j}+c(pos_i,i)+1+c(j,i)+1
\]

这里的式子跟上面不一样是因为这个式子归纳了 \(pos_i>j\) 的情况。

我们还需要考虑第2中情况,即它不变时的方案。注意到这篇论文的内容 我们发现我们需要考虑当前不动对后面的影响。你发现对于中间( \(x\) 和移动到的点之间)未考虑的点 \(i\) 它一定会移动到 \(x\) 的前面去,那么轮到 \(i\) 的时候 \(x\) 的前面已经排了 \(x-1,x-2,...,i+1\),所以它还需要额外算上 \(x-i\),剩下的部分会在上面考虑到。对于移动到的点之后的点肯定在轮到移动到的点的时候就考虑到了。

于是转移式就是:

\[dp_{i,pos_i}=\min\{dp_{i+1,j}+\sum_{k=i+1}^{j-1}[a_k<i](i-a_k)\}
\]

(\(a_k\) 是序列第 \(k\) 个)

于是我们就可以在 \(\Theta(n^2)\) 的时间复杂度内解决这个问题了。

不过我们要求最后的答案的话我们需要统计一下每一个点移动的点,具体可以见代码。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define INF 0x7f7f7f7f
#define MAXN 1005 int n,tot,pos[MAXN],dp[MAXN][MAXN],pre[MAXN]; struct node{
int x,ind;
}fuck[MAXN]; bool cmp1 (node a,node b){return a.x > b.x;}
bool cmp2 (node a,node b){return a.ind < b.ind;} template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} void dfs (int i,int j){
if (i == n) return ;
if (pos[i] != j) tot ++,dfs (i + 1,j);
else dfs (i + 1,pre[i]);
} signed main(){
read (n);
for (Int i = 1;i <= n;++ i) read (fuck[i].x),fuck[i].ind = i;
sort (fuck + 1,fuck + n + 1,cmp1);
for (Int i = 1;i <= n;++ i) pos[i] = fuck[i].ind,fuck[i].x = i;
sort (fuck + 1,fuck + n + 1,cmp2);
memset (dp,0x7f,sizeof (dp));
++ n,dp[n][n] = 0,fuck[n].x = n;
for (Int i = n - 1;i;-- i){
int v1 = 1,v2 = 1;
for (Int j = 1;j < pos[i];++ j) v1 += (fuck[j].x < i);
for (Int j = 1;j <= n;++ j) v2 += (fuck[j].x < i),dp[i][j] = min (dp[i][j],dp[i + 1][j] + v1 + v2);
for (Int j = pos[i] + 1,tmp = 0;j <= n;++ j){
if (dp[i + 1][j] + tmp < dp[i][pos[i]]) dp[i][pos[i]] = dp[i + 1][j] + tmp,pre[i] = j;
if (fuck[j].x < i) tmp += i - fuck[j].x;
}
}
int ans = 0x7f7f7f7f,pos = 0;
for (Int i = 1;i <= n;++ i) if (dp[1][i] < ans) ans = dp[1][i],pos = i;
dfs (1,pos),write (tot),putchar ('\n');
return 0;
}

参考博客

https://www.cnblogs.com/yimmortal/p/10160630.html 建议与论文一起服用

https://blog.csdn.net/icefox_zhx/article/details/80014541 可以看一下代码实现(或者看我的也可以)

方块消除

题目大意

有一个数列,每次可以消掉一掉连续的颜色相同的一块,贡献就是 \(x^2\),其中 \(x\) 是长度。问最大贡献。

思路

不知道如何去讲思考过程,所以直接讲方法?

我们可以设 \(f_{l,r,i}\) 表示消掉 \(l,r\) 并且假设在 \(r\) 的右边存在一个长度为 \(i\) 并颜色与 \(r\) 相同的块的最大贡献。于是我们可以得到转移式:

\[f_{l,r,i}=f_{l,r-1,0}+(len_r+i)^2
\]
\[f_{l,r,i}\to f_{l,j,i+len_r}+f_{j+1,r-1,0}
\]

显然,想一下就明白了。最后答案就是 \(f_{1,n,0}\)

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define MAXN 205 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} int sqr (int x){return x * x;}
int n,col[MAXN],pre[MAXN],len[MAXN],dp[MAXN][MAXN][MAXN]; signed main(){
read (n);
for (Int i = 1;i <= n;++ i) read (col[i]);
for (Int i = 1;i <= n;++ i) read (len[i]),pre[i] = pre[i - 1] + len[i];
for (Int leng = 1;leng <= n;++ leng){
for (Int l = 1;l + leng - 1 <= n;++ l){
int r = l + leng - 1;
for (Int i = 0;i <= pre[n] - pre[r];++ i) dp[l][r][i] = dp[l][r - 1][0] + sqr (len[r] + i);
for (Int i = l;i <= r - 1;++ i)
for (Int j = 0;j <= pre[n] - pre[r];++ j)
if (col[i] == col[r]) dp[l][r][j] = max (dp[l][r][j],dp[l][i][len[r] + j] + dp[i + 1][r - 1][0]);
}
}
write (dp[1][n][0]),putchar ('\n');
return 0;
}

奥运物流

题目大意

有一个 \(n\) 个点的图,给出参数 \(k\),每个点有一个后继,每个点有两个参数,分别为 \(R(x),C(x)\),其中 \(C(x)\) 是给定参数,\(R(x)\) 由 \(C(x)\) 计算,公式为:

\[R(x)=C(x)+k\sum_{v\in son_u}R(v)
\]

现在你有 \(m\) 次修改机会,每次可以更改一个点的后继。求 \(R(1)\) 的最大值。

思路

下面定义 \(d(i)\) 表示 \(i\to 1\) 的距离。

首先我们发现这个图一定是一个森林,就是很多棵树,然后树的根构成一个环。

我们发现对于对于一个点 \(x\),他对 \(R(1)\) 的贡献就是 \(C(x)\times k^{d(x)}/(1-k^{len})\),其中 \(len\) 是环上点的数量。具体说明可以分类讨论,分别考虑环上的点以及树上的点来说明。

然后我们如果枚举环的长度的话,那么我们就只需要让 \(\sum_{x=1}^{n}C(x)\times k^{d(x)}\) 最大。这个问题就类似于没有上司的舞会。

我们考虑设计状态 \(dp_{u,i,d}\) 表示以 \(u\) 为根的子树改变了 \(i\) 次,点 \(i\) 深度为 \(d\) 的最大贡献。于是,我们可以得到转移式:

\[dp_{u,i,d}\to dp_{u,j,d}+\max\{dp_{v,i-j,d+1}+dp_{v,i-j-1,1}\}
\]

转移显然。

最后再把环上的点都合并起来就行了。在实现的时候为了方便我们可以直接破环,把整个图变成一棵树,以 \(1\) 为根做上述 \(\text{dp}\) 即可。

时间复杂度最坏 \(\Theta(n^5)\) (假设 \(n,m\) 同阶)

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define double long double
#define Int register int
#define MAXN 65 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} int n,m,s[MAXN];
vector <int> G[MAXN];
double k,c[MAXN],pw[MAXN],tmp[MAXN][MAXN],dp[MAXN][MAXN][MAXN]; void dfs (int u,int dep,int up){
for (Int i = 0;i <= up;++ i) for (Int j = 0;j <= dep;++ j) dp[u][i][j] = c[u] * pw[j];
for (Int v : G[u]){
dfs (v,dep + 1,up);
memset (tmp,0,sizeof (tmp));
for (Int i = 0;i <= up;++ i)
for (Int j = 0;i + j <= up;++ j)
for (Int d = 0;d <= dep;++ d){
tmp[i + j][d] = max (tmp[i + j][d],dp[u][i][d] + dp[v][j][d + 1]);
if (j > 0) tmp[i + j][d] = max (tmp[i + j][d],dp[u][i][d] + dp[v][j - 1][1]);
}
for (Int i = 0;i <= up;++ i) for (Int j = 0;j <= dep;++ j) dp[u][i][j] = tmp[i][j];
}
} double calc (int up){
dfs (1,0,up);
return dp[1][up][0];
} signed main(){
read (n,m);scanf ("%Lf",&k);
pw[0] = 1;for (Int i = 1;i <= n;++ i) pw[i] = pw[i - 1] * k;
for (Int i = 1;i <= n;++ i) read (s[i]);
for (Int i = 1;i <= n;++ i) scanf ("%Lf",&c[i]);
double ans = 0;
for (Int d = 2,p = s[1];p != 1;++ d,p = s[p]){
for (Int i = 1;i <= n;++ i) G[i].clear ();
int t = s[p];s[p] = 1;
for (Int i = 2;i <= n;++ i) G[s[i]].push_back (i);
ans = max (ans,calc (m - (t != 1)) / (1 - pw[d]));
s[p] = t;
}
printf ("%.2Lf\n",ans);
return 0;
}

题解 Sue的小球/名次排序问题/方块消除/奥运物流的更多相关文章

  1. BZOJ-2037 Sue的小球 DP+费用提前

    似乎很早时学长考过很类似的? 2037: [Sdoi2008]Sue的小球 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 558 Solved: 300 ...

  2. 【BZOJ2037】Sue的小球(动态规划)

    [BZOJ2037]Sue的小球(动态规划) 题面 BZOJ 题解 莫名想到这道题目 很明显是一样的 设\(f[i][j][0/1]\)表示已经接到了\(i-j\)这一段的小球 当前在\(i\)或者在 ...

  3. 【BZOJ2037】[Sdoi2008]Sue的小球 区间DP+费用提前

    [BZOJ2037][Sdoi2008]Sue的小球 Description Sue和Sandy最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue有一支轻便小巧的小船.然而 ...

  4. 2037: [Sdoi2008]Sue的小球

    2037: [Sdoi2008]Sue的小球 链接 题解 论文 代码 #include<cstdio> #include<algorithm> #include<cstr ...

  5. [Luogu2135] 方块消除【区间Dp】

    Online Judge:P2135 方块消除(这题不用预处理) Label:区间Dp 题目描述 Jimmy最近迷上了一款叫做方块消除的游戏.游戏规则如下:n个带颜色方格排成一列,相同颜色的方块连成一 ...

  6. 第八讲:HTML5中canvas实现小球击打小方块游戏

    源码:http://download.csdn.net/detail/liumingm900913/7469969 游戏开发流程: 1.创建画布: 将画布放在div标签里面,这样能够控制画布居中的位置 ...

  7. [BNUZOJ1261][ACM][2016北理校赛]方块消除(栈,字符串)

    玩过方块消除游戏吗?现在规定当有两个或两个以上相邻且颜色相同的方块在一起的时候,它们就会产生消除反应.当存在多个消除反应同时产生时,最下的反应先执行.现在只给你其中一列,求最后剩下的方块结果. 输入要 ...

  8. 洛谷 P2466 Sue的小球 解题报告

    P2466 [SDOI2008]Sue的小球 题目描述 Sue和Sandy最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue有一支轻便小巧的小船.然而,Sue的目标并不是当 ...

  9. P2135 方块消除

    题目描述 Jimmy最近迷上了一款叫做方块消除的游戏.游戏规则如下:n个带颜色方格排成一列,相同颜色的方块连成一个区域(如果两个相邻方块颜色相同,则这两个方块属于同一区域).为简化题目,将连起来的同一 ...

随机推荐

  1. 解决->maven下载失败bug

    一.前言: 经过一个下午的奋斗(谷歌,视频...重装)后终,于暂时解决了上一篇文章中的bug 传送门:https://blog.csdn.net/weixin_44092288/article/det ...

  2. 提交Spark作业遇到的NoSuchMethodError问题总结

    测试应用说明 测试的Spark应用实现了同步hive表到kafka的功能.具体处理流程: 从 ETCD 获取 SQL 语句和 Kafka 配置信息 使用 SparkSQL 读取 Hive 数据表 把 ...

  3. go语言调用everything的SDK接口

    介绍 官方SDK地址 本项目会将官方dll编译到可执行程序中,运行时无需考虑dll问题. 根据官方介绍,使用SDK前需要运行everything程序. 执行go build -tag ASCII时编译 ...

  4. 剑指 Offer 38. 字符串的排列

    剑指 Offer 38. 字符串的排列 输入一个字符串,打印出该字符串中字符的所有排列. 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素. 示例: 输入:s = "abc" ...

  5. [源码解析] 深度学习流水线并行 PipeDream(5)--- 通信模块

    [源码解析] 深度学习流水线并行 PipeDream(5)--- 通信模块 目录 [源码解析] 深度学习流水线并行 PipeDream(5)--- 通信模块 0x00 摘要 0x01 前言 0x02 ...

  6. 分组概念&贪婪与懒惰

    分组概念&贪婪与懒惰 1.分组 2.贪婪和懒惰 3.懒惰 4.处理选项 5.实例:百度搜索结果页面源码中获取当前页的10个标题 5.1页面源码分析规律 5.2正则表达式,匹配出10个标题 这是 ...

  7. 硕盟USB3.0 转RJ45千兆网卡 TYPE A USB3.0 TO RJ45

    硕盟SM-A44是一款USB3.0转RJ45千兆网口转换器.这是一种高性能和低开销的解决方案.转换USB端口到10 / 100/ 1000M以太网端口可以让您的笔记本,台式机电脑能够通过USB接口连接 ...

  8. salesforce零基础学习(一百零七)Dynamic Action

    说一下项目中常见的甲方的需求.背景如下:Order在SF端生成以后,在status为completed以后,需要点击按钮同步到SAP或者其他的MDM,客户希望的是,如果 order的状态为 compl ...

  9. C# 获得当前方法 和 方法调用链 的 方法

    一个获得方法名的方法,depth表示调用此方法的回溯深度. 比如,A方法调用B方法,B方法调用GetCurrentMethodFullName(2),那么得到的结果是A方法的全名(namespace+ ...

  10. 九、Abp vNext 基础篇丨评论聚合功能

    介绍 评论本来是要放到标签里面去讲的,但是因为上一章东西有点多了,我就没放进去,这一章单独拿出来,内容不多大家自己写写就可以,也算是对前面讲解的一个小练习吧. 相关注释我也加在代码上面了,大家看看代码 ...