博客
关于我
中石油训练混合训练第七场
阅读量:290 次
发布时间:2019-03-01

本文共 3288 字,大约阅读时间需要 10 分钟。

题目描述

在某个游戏中,你接受了一个任务。这个任务要求你消灭n只狼。这些狼排成一排,每只狼都有两个攻击力a和b。如果你消灭一只狼,需要的代价是这只狼的a攻击力加上它旁边的狼的b攻击力。每消灭一头狼,它两边的狼(如果有)会并在一起,仍然保持一排。
你需要求出:消灭所有狼的最小代价。
输入
输入第一行为一个正整数n。
输入第二行为n个非负整数,按顺序表示每只狼的a攻击力;第三行为n个非负整数,表示每只狼的b攻击力。
输出
输出一行一个整数,为最小的代价。
样例输入 Copy

3 3 5 7 8 2 0

样例输出 Copy

17

提示

对于100%的数据,满足1≤n≤400,每只狼的a攻击力和b攻击力均不超过100000。
首先说杭电有这个题
先附上一片博客:
题目大意:一排狼,消灭这头狼需要消耗代价为这只狼的a战斗力和这头狼身边的狼的b战斗力
所以先将输入的数据进行预处理:

for(int i=1;i<=n;i++)	dp[i][i]=a[i]+b[i-1]+b[i+1];///左右两边都加上

当一只狼被消灭之后,原先相邻的狼会靠在一起(相邻)

设消灭第 i 匹狼到第 j 匹狼的最小代价为dp [ i ][ j ],那么很显然答案就是dp [ 1 ][ n ]。
过程中需要枚举 i 到 j 之间的区间长度以及 k 即可
在这里插入图片描述
刚开始因为是dp[i][j]所以最后都要加上区间两侧的狼的b攻击力
然后下面进行枚举的时候,还要取最小值
这里枚举得是i——j的部分有一个类似于桥梁的东西 dp[i][k-1] dp[k+1][j] 和a

ll temp=dp[i][k-1]+a[k]+b[i-1]+b[j+1]+dp[k+1][j];dp[i][j]=min(dp[i][j],temp);

经过一波操作之后将最终结果dp[i][n]输出

#include 
using namespace std;#define wuyt maintypedef long long ll;#define HEAP(...) priority_queue<__VA_ARGS__ >#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >template
inline T min(T &x,const T &y){ return x>y?y:x;}template
inline T max(T &x,const T &y){ return x
>=1; x=(x*x); } return res;}ll maxx=-1;ll minn=inf;ll num2[maxn];ll num[maxn];ll res,ans;int sum=0;map
mp;vector
vet;priority_queue
,greater
> xiaogen;queue
duilie;priority_queue
,less
> que;ll a[500],b[500];ll dp[500][500];int main(){ int n=read; for(int i=1;i<=n;i++) a[i]=read; for(int i=1;i<=n;i++) b[i]=read; memset(dp,0x3f3f3f3f,sizeof dp); for(int i=1;i<=n;i++) dp[i][i]=a[i]+b[i-1]+b[i+1];///左右两边都加上 for(int i=n-1;i>=1;i--){ for(int j=i+1;j<=n;j++){ ll temp1=dp[i+1][j]+a[i]+b[i-1]+b[j+1]; ll temp2=dp[i][j-1]+a[j]+b[i-1]+b[j+1]; dp[i][j]=min(temp1,temp2); for(int k=i+1;k

好朋友

题目描述

众所周知,XZ&CHR是好朋友……
这天,CHR打算考验一下XZ与自己的默契度,他想了n个正整数:a1~ an,为了不为难XZ,CHR只要求说出一个数,这个数是a1 ~ an中任何一个数的倍数即可。当然,这还是十分困难,XZ知道后,觉得这很难,就来问问你:如果他在1~m中随机说出一个数,通过考验的概率是多少?

输入

第一行输入一个正整数T,代表有T组数据。
对于每一组数据,第一行输入n,m, 第二行输入a1~an,含义见题目描述。

输出

为防止有精度问题,对于每一组数据输出概率乘上m,即一个正整数代表答案。
样例输入

12 102 3

样例输出

7

提示

样例解释:2、4、6、8、10是2的倍数,其他数中3、9是3的倍数,共7个。
【数据范围】
对于30%的数据,m ≤ 1000。
对于另外20%的数据,n = 1。
对于另外20%的数据,n = 2。
对于所有数据,n ≤ 10,1<ai ≤ m ≤ 109,T ≤ 10000。

在鄙人的里面

在这里插入图片描述
利用相似的做法,来解决这个问题
看了感觉真的很秀,当天晚上调了好长时间的问题竟然被巨巨如此之短的代码解决,感觉真是太秀了

需要注意的是:需要求两个数的最小公倍数,就像是上面那道题目的3*5类似的情况,因为3和5都是质数,所以就直接求了乘积,但是在这到题目里面并不适用,因此求两个数的最小公倍数才是正确的解决方式,每次循环的时候,要改符号(根据容斥原理来解决)

但是上面大佬的一手DFS确实秀到我了,很强

#include 
using namespace std;#define wuyt maintypedef long long ll;ll read(){ ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();if(c == '-')Nig = -1,c = getchar();while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();return Nig*x;}#define read read()const ll inf = 1e15;const ll INF = 0x3f3f3f3f;const int maxn = 2e6 + 7;const int mod = 1e9 + 7;ll gcd(ll a,ll b){ ll t; while(b!=0) { t=a%b; a=b; b=t; } return a;}ll lcm(ll a,ll b){ return a/gcd(a,b)*b;}void DFS(int now,int op,ll fenmu){ if(now!=1) ans+=m/fenmu*(op); for(int i=now;i<=n;i++) DFS(i+1,-op,lcm(fenmu,num[i]));}int main(){ int cnt=read; while(cnt--){ n=read,m=read; for(int i=1;i<=n;i++) num[i]=read; ans=0; /// 第一次之后*-1,所以开始要是-1而不是1 DFS(1,-1,1); cout<
<

转载地址:http://uloo.baihongyu.com/

你可能感兴趣的文章
MySQL I 有福啦,窗口函数大大提高了取数的效率!
查看>>
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>
MySQL InnoDB 三大文件日志,看完秒懂
查看>>
Mysql InnoDB 数据更新导致锁表
查看>>
Mysql Innodb 锁机制
查看>>
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>
Mysql InnoDB存储引擎中的checkpoint技术
查看>>
Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
查看>>
MySQL InnoDB引擎的锁机制详解
查看>>
Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
查看>>
mysql InnoDB数据存储引擎 的B+树索引原理
查看>>
mysql innodb通过使用mvcc来实现可重复读
查看>>
mysql insert update 同时执行_MySQL进阶三板斧(三)看清“触发器 (Trigger)”的真实面目...
查看>>
mysql interval显示条件值_MySQL INTERVAL关键字可以使用哪些不同的单位值?
查看>>
Mysql join原理
查看>>
MySQL Join算法与调优白皮书(二)
查看>>
Mysql order by与limit混用陷阱
查看>>