题目名称

run

homework

cut

输入

run.in

homework.in

cut.in

输出

run.out

homework.out

cut.out

每个测试点时限

1秒

1秒

2秒

内存限制

64MB

64MB

64MB

测试点数目

10

10

10

每个测试点分值

10

10

10

是否有部分分

题目类型

传统

传统

传统

run

Background:

穿过时空隧道,小明来到了秦朝。我是谁?我在哪?

“哈哈哈,金科,发什么呆呢,你的刺杀已经失败了!”秦王躲在柱子后狂妄的笑。

一股热血在小明体内流动,他竟情不自禁地追了上去。

Description:

宫殿里一共有n根柱子,假设柱子在二维平面内的位置为(xi,yi)。金科现在在一号柱子,秦王现在在n号柱子。金科(小明)会飞檐走壁所以他从i号柱子到j号柱子的距离为min(|xi-xj|,|yi-yj|)。深知自己并不能刺杀秦王,所以小明知道事实上自己竭尽全力,也离秦王有一步之遥,所以小明想知道自己到达n号柱子的最短距离-1是多少,因为这将是他人生能走过的最后的路。

Input:

第一行一个数n。

接下来n-1行每行两个数x,y分别表示xi和yi。

Output:

一行一个数表示从1号柱子走到n号柱子的最短距离减去1的长度。

Sample input:

5

2 2

1 1

4 5

7 1

6 7

Sample output:

1

Hint:

1->2->4->5最短距离为2,答案为1。

对于30%的数据,n<=1000。

对于100%的数据,n<=200000,0<xi,yi<1e9

数据保证答案>0,不然很奇怪。。

题解:我们发现每个点分别于横纵坐标相邻的点连边就可以解决问题了,建边后直接跑最短路就可以了。最后不要忘记答案-1.(可以自己构图验证正确性)

用堆优化+dijistra的板子

#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
#define maxn 200005
#define maxm 1000005
bool vis[maxn];
int L,n,tot,head[maxn],dis[maxn];
inline void read(int &x){x=0;int f=1;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}x*=f;
}
struct Point{int x,y,id;
}p[maxn];
struct edge{int nxt,v,w;
}G[maxm];
struct rp{int id,key;rp(int a,int b){id=a, key=b;}
};
bool cmp2(Point a, Point b){return a.x < b.x;
}
bool cmp1(Point a, Point b){return a.y < b.y;
}
struct cmp{bool operator()(const rp& a, const rp& b){return a.key > b.key;}
};void add(int u, int v, int w){G[++tot].nxt = head[u];G[tot].w = w;G[tot].v = v;head[u] = tot;G[++tot].nxt = head[v];G[tot].w = w;G[tot].v = u;head[v] = tot;
}
void dijistra(){memset(dis, 127, sizeof(dis));priority_queue <rp,vector<rp>,cmp> q;q.push(rp(1, 0));dis[1] = 0;while(!q.empty()){rp u = q.top();q.pop();if(vis[u.id])continue;vis[u.id] = 1;for(int j = head[u.id]; j; j = G[j].nxt){int v = G[j].v;if(dis[v] > dis[u.id] + G[j].w){dis[v] = dis[u.id] + G[j].w;q.push(rp(v, dis[v]));}}}
}
int main()
{    freopen("run.in","r",stdin);freopen("run.out","w",stdout);read(n);for(int i = 1; i <= n; i++)read(p[i].x), read(p[i].y), p[i].id = i;sort(p+1, p+1+n, cmp2);for(int i = 1; i < n; i++)add(p[i].id, p[i+1].id, p[i+1].x - p[i].x);sort(p+1, p+1+n, cmp1);for(int i = 1; i < n; i++)add(p[i].id, p[i+1].id, p[i+1].y - p[i].y);dijistra();printf("%d\n",dis[n]-1);
}

homework

Background:

小哪吒在开学前一天补作业。。。

Description:

明天就要开学了!所以小哪吒需要尽快写完作业。现在,他有n份作业需要写,因为小哪吒精通变化,他可以再变出两只手来,所以他可以同时写两份作业。小哪吒两双手写同一份作业的时间是不一样的。为了节约时间,他用火眼睛睛看出了两双手写同一份作业分别需要ai,bi的时间。同样的,为了节约时间,他不会更改做题的顺序,即他会从第一份作业一直做到第n份作业。他唯一不知道的是,他能写完作业的最短时间。你能帮他求出来吗?

Input:

第一行一个数n表示作业的数目。

接下来n行每行两个数ai,bi分别表示小哪吒两双手写这份作业的时间。

Output:

一行一个数表示写作业的最短时间。

Sample input:

3
1 3
1 3
1 3

Sample output:

3

Hint:

对于样例,用第一双手做完所有作业。

对于40%的数据,n<=20。

对于100%的数据,n<=2000。ai,bi<=3000。

题解:我们用dp[i][0/1][j]表示去做第i份作业用第0/1只手时,另外一双手还需要做j的时间才能做完作业的最小时间;

dp[i][j][k] = min( dp[i - 1][ j ][ k+a[i - 1][ j ] ] + a[i - 1][ j ],  dp[i - 1][ j^1 ][ a[i - 1][ j^1 ] ] , 但我们有可能在0手有空时不一定用0手而是等1手完了用1手,

而这样当 k+a[i - 1][ j ]  = 0我们刚好就去用了空闲的手,故我们反着推就可以了,因为dp[i][j][k] k=0 时有可能那只手已经休息了很久了;

注意dp[i]中第i份作业还没做,所以我们最后要加上剩下的时间

#include <bits/stdc++.h>using namespace std;
#define maxn 2005
int dp[maxn][2][3005], a[maxn][2];
inline void read(int &x){x=0;int f=1;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}x*=f;
}int main(){///freopen("homework.in","r",stdin);//freopen("homework.out","w",stdout);int n;read(n);for(int i = 1; i <= n; i++)read(a[i][0]), read(a[i][1]);memset(dp, 0x3f, sizeof(dp));dp[1][0][0] = dp[1][1][0] = 0;for(int i = 1; i <= n; i++)for(int j = 0; j < 2; j++)for(int k = 0; k <= 3000; k++){dp[i+1][j][max(0, k-a[i][j])] = min(dp[i+1][j][max(0, k-a[i][j])], dp[i][j][k]+a[i][j]);dp[i+1][j][max(0, a[i][j^1]-k)] = min(dp[i+1][j][max(0, a[i][j^1]-k)] , dp[i][j^1][k]+k);}int ans = 1e9;for(int j = 0; j < 2; j++)for(int k = 0; k <= 3000; k++)ans = min(ans, dp[n][j][k] + max(k, a[n][j]));printf("%d\n",ans);
}

cut

Background:

伐木工Zxr非常懒惰了,所以他在伐木的时候只会找准木头被虫蛀过的腐朽的地方砍下去。

Description:

一块有N-1处被虫蛀过的地方,假设被虫蛀过的地方长度不计。这n-1个虫蛀将木头分成了n块,题目将依次给出这n块木头的长度。懒惰的zxr最多只想砍m次,并且希望可以借此把这块木头分得尽量均匀,即希望使砍伐后连续的木块中最长的尽量短。这个时候聪明的你跳了出来“我不仅能算出这个最短长度,我还能算出方案数!”

Input:

第一行两个数n,m。

接下来一行n个数分别表示这N块木头的长度。

Output:

一行两个数分别表示最短的最长长度和方案数。

Sampleinput:

3 2

1 1 10

Sampleoutput:

10 2

Hint:

两种砍的方法: (1)(1)(10)和(1 1)(10)。

对于30%的数据,n<=10,

对于100%的数据,n<=50000,

0<=m<=min(n-1,1000),1<=Li<=1000.

题解:

第一问是一个十分显然的二分,贪心Check(),很容易就能求出最小的最大长度 Len 。

第二问求方案总数,使用 DP 求解。

  使用前缀和,令 Sum[i] 为前i根木棍的长度和。

  令 f[i][j] 为前i根木棍中切 j 刀,并且满足最长长度不超过 Len的方案数,那么:

    状态转移方程: f[i][j] = Σ f[k][j-1]   ((1 <= k <= i-1) &&  (Sum[i] - Sum[k] <= Len))  

  这样的空间复杂度为 O(nm) ,时间复杂度为 O(n^2 m) 。显然都超出了限制。

  下面我们考虑 DP 的优化。

  1) 对于空间的优化。

    这个比较显然,由于当前的 f[][j] 只与 f[][j-1] 有关,所以可以用滚动数组来实现。

    f[i][Now] 代替了 f[i][j] , f[i][Now^1] 代替了 f[i][j-1] 。为了方便,我们把 f[][Now^1] 叫做 f[][Last] 。

    这样空间复杂度为 O(n) 。满足空间限制。

  2) 对于时间的优化。

    考虑优化状态转移的过程。

    对于 f[i][Now] ,其实是 f[mink][Last]...f[i-1][Last] 这一段 f[k][Last] 的和,mink 是满足 Sum[i] - Sum[k] <= Len 的最小的 k ,那么,对于从 1 到 n 枚举的i,相对应的 mink 也一定是非递减的(因为 Sum[i] 是递增的)。我们记录下 f[1][Last]...f[i-1][Last] 的和Sumf,mink 初始设为 1,每次对于i将 mink 向后推移,推移的同时将被舍弃的 p 对应的 f[p][Last] 从Sumf中减去。那么 f[i][Now] 就是Sumf的值。

    这样时间复杂度为 O(nm) 。满足时间限制。

#include <bits/stdc++.h>using namespace std;
#define maxn 50005
#define mod 10007
int dp[maxn][2], a[maxn], sum[maxn], L, n, m, Ml;
inline void read(int &x){x=0;int f=1;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}x*=f;
}bool check(int mid){int ll = 0, i = 0, group = 1, flag = 0;while(i <= n){if(ll + a[++i] <= mid)ll += a[i];else if(a[i] > mid)return false;else {group++;if(group > m + 1)return false;ll = a[i];}}return true;
}
void bs(){int l = Ml, r = sum[n];while(l != r){int mid = (l + r) >> 1;if(check(mid))r = mid;else l = mid+1;}L = r;//取大的printf("%d ",L);
}
void Dp(){int sumf = 0, mink = 0, ans = 0;int k = 0;for(int j = 0; j <= m; j++){sumf = 0; mink = 1;//一定要记得更新,忘了更新这个地方,WA了好多次for(int i = 1; i <= n; i++){if(!j){if(sum[i] <= L)dp[i][k] = 1;}else {while(mink < i && sum[i] - sum[mink] > L){sumf -= dp[mink][k^1];sumf = (sumf + mod) % mod;mink++;            }    dp[i][k] = sumf;}           sumf = (sumf + dp[i][k^1]) % mod;}ans += dp[n][k];ans %= mod;k^=1;//滚动数组
    }printf("%d\n",ans);
}
int main(){freopen("cut.in","r",stdin);freopen("cut.out","w",stdout);read(n),read(m);for(int i = 1; i <= n; i++){read(a[i]);Ml = max(Ml, a[i]);sum[i] = sum[i-1] + a[i];}bs();Dp();
}

转载于:https://www.cnblogs.com/EdSheeran/p/8496929.html

18寒假最后一测+dijistra模板相关推荐

  1. Abp 0.18.0 正式发布! -ABP CLI,新模板和其他功能

    ABP CLI, v0.18版本新模板和其他功能 ABP v0.18已发布, 包含解决的80+个issue, 550+次提交. 网站更改 abp.io网站完全更新以突出ABP框架的目标和重要功能.文档 ...

  2. Abp v0.18.0 新版本: MVC Module 启动模板

    0.18.0将于近期发布, 本文内容针对于0.18.0版本. MVC模块启动模板 可用此模板开发基于模块开发最佳实践和约定的可复用 应用程序模块 . 它同样适用于开发微服务. 如何开始? 你可以使用A ...

  3. 18.2.2 简单的类模板

    18.2.2 简单的类模板 下面用前面的一个例子来说明,为数组定义一个类模板,该数组要对索引值进行边界检查,确保索引值是合法的.尽管标准库提供了数组模板的完整实现方式,但建立自己的数组模板有助于理解模 ...

  4. 2-Arduino小车测速模板安装与测试

    Arduino智能小车--小车测速 准备材料 1.     测速模块 2.      3.     固定铜柱 a)      建议铜柱长度30CM,大小为M3 b)      由于铜柱导电,有些电路板 ...

  5. 博客摘录「 项目启动会ppt_“项目启动会”必须要汇报的18个要素(附PPT模板)| 推荐」2023年5月26日转载自:http://t.csdn.cn/z5xg8

    项目经理作为项目的总负责人,项目启动会是接手项目后第一次比较正式的会议.经过前期的立项.调研.科研.设计的过程,项目的建设范围.建设周期以及建设目标逐渐地明细,但是还没有进行详细资料的整理和总结.此时 ...

  6. [JZOJ5666]【GDOI2018Day2模拟4.18】法力风暴(分治NTT 模板)

    Description 有 2≤n≤105,0≤Ai,k≤109 2 ≤ n ≤ 10 5 , 0 ≤ A i , k ≤ 10 9 2 ≤ n ≤ 10^5 ,0 ≤ A_i ,k ≤ 10^9 S ...

  7. [01-23][ dcwz电影合集][10部][18:30发布][亲测]

    1.08爆笑喜剧大片<火箭科学> DVD中字 2.08动作惊悚大片<法国黑金/流血的谎言> DVD中字 3.08惊悚动作片<跨越死亡线> DVD中字 4.07最新奥 ...

  8. kubeadm方式部署k8s集群(1.18版本,亲测可用)

    文章目录 一.系统环境 1.设置系统主机名以及Host文件 2.关闭防火墙 3.关闭系统Swap 二.安装Docker 1.安装docker 2.所需镜像 三.安装kubelet.kubeadm 和 ...

  9. 关于模板引擎handlebars.js基本用法

    说明:模板引擎主要针对于渲染DOM,取代了字符串拼接,用下面的代码亲测handlebars模板引擎比字符串拼接渲染DOM慢了20ms, 这里配置一个在线DEMO,简单说明下handlebars.js的 ...

最新文章

  1. NYOJ 138 找球号(二)哈希表
  2. js 静止f1到f12 和屏蔽鼠标右键
  3. CSDN 开学见面礼!3 周带你 Get 大厂工程师基础能力
  4. GO编程程序员修炼秘籍:十本经典书单
  5. Python3 中你知道有多少错误和异常
  6. Bootstrap CSS 编码规范之注释
  7. Windows环境下log4cxx的编译及使用(转载)
  8. 拓端tecdat:Python集成学习:自己编写构建AdaBoost分类模型可视化决策边界及sklearn包调用比较
  9. redisconnectionfactory 没有这个bean_浅析Spring中bean的作用域
  10. Latex所有常用数学符号整理
  11. Android测试总结
  12. 电脑硬盘怎么分区?C盘/D盘/E盘......快来创建自己的DIY磁盘吧!
  13. 生产大数据集群架构图
  14. EasyExcel导出合并单元格
  15. 小白通过JDBC在AndroidStudio一步步来访问MYSQL数据库
  16. FlashVml2.0(WEB上的PhotoShop+Flash、VML最强开发工具)[推荐]
  17. 青龙面板-花花阅读6.25 最新修复版
  18. #300. 【CTSC2017】吉夫特
  19. 用R语言绘制ROC曲线
  20. R语言使用caret包的train函数构建adaboost模型、模型调优、自定义设置trainControl函数和tuneLength参数

热门文章

  1. Java一些八卦集合类
  2. vim 块操作、多文件操作、多窗口操作命令
  3. 好用的ToolStripManager类
  4. seaborn绘图后得到分布参数
  5. kaggle上面的score以及ROC_AUC数值咋回事
  6. 修改win7编码为utf-8
  7. 计算机系统 程序和指令
  8. 5.13 卡尔曼滤波
  9. java并发核心知识体系精讲_JVM核心知识体系
  10. Mapper.xml映射文件---Mybatis学习笔记(八)