题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3541
题目大意:
在数轴上,有n个按钮,位置递增为d1,d2,..dn,每个按钮对应一个时间为t1,t2,...tn.每次每个按钮按下后,t1秒后会自动弹起来。每走单位距离花费单位时间,问以怎样的顺序按,能够保证所有 的按钮都能够被按下去。
解题思路:
区间dp.
这题hdu 4053提交过不了,spj可能有问题。
对于某一区间A~B的按钮,一定是先按某个端点,如果不是,假设先按中间的K,然后肯定要按一个端点,再之后会按另外一个端点,中间肯定会经过K点,所以先按k不如后按k。
dp[i][j][0]表示在区间i~j内先按左边端点能达到的最小的时间,dp[i][j][1]表示先按右端点能达到的最小时间。
dp[i][j][0]=Min(dp[i+1][j][0]+dp[i+1]-dp[i],dp[i+1][j]+dp[j][-dp[i]);
path[i][j][]表示对应状态表示的端点(左还是右)。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x3fffffff
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; //freopen("data.in","r",stdin);
//freopen("data.out","w",stdout); #define Maxn 220 ll dp[Maxn][Maxn][2];
int pa[Maxn][Maxn][2];
//dp[i][j][0]表示区间i~j从左边端点开始按 dp[][][1]表示从右边端点开始
//path[i][j][k]表示与之对应的状态。
int ti[Maxn],di[Maxn];
int n; int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&ti[i]);
for(int i=1;i<=n;i++)
scanf("%d",&di[i]);
memset(dp,0,sizeof(dp)); //时间为0
for(int gap=2;gap<=n;gap++)
{
for(int i=1;i+gap-1<=n;i++)
{
int j=i+gap-1; if(dp[i+1][j][0]+di[i+1]-di[i]<dp[i+1][j][1]+di[j]-di[i])
{
dp[i][j][0]=dp[i+1][j][0]+di[i+1]-di[i];
pa[i][j][0]=0;//表示从左边过来
}
else
{
dp[i][j][0]=dp[i+1][j][1]+di[j]-di[i];
pa[i][j][0]=1;//表示从右边走
}
if(ti[i]<=dp[i][j][0]||dp[i][j][0]>=INF)
dp[i][j][0]=INF; if(dp[i][j-1][1]+di[j]-di[j-1]<=dp[i][j-1][0]+di[j]-di[i])
{
dp[i][j][1]=dp[i][j-1][1]+di[j]-di[j-1];
pa[i][j][1]=1; //从右边
}
else
{
dp[i][j][1]=dp[i][j-1][0]+di[j]-di[i];
pa[i][j][1]=0;//从左边
}
if(ti[j]<=dp[i][j][1]||dp[i][j][1]>=INF)
dp[i][j][1]=INF; //置为无效状态
}
}
int l,r,va;
if(dp[1][n][0]<INF) //有效状态
{
printf("%d",1);
l=2,r=n;
va=pa[1][n][0];
}
else if(dp[1][n][1]<INF)
{
printf("%d",n);
l=1,r=n-1;
va=pa[1][n][1];
}
else
{
printf("Mission Impossible\n");
continue;
}
while(l<=r)
{
if(va==0)
{
printf(" %d",l);
va=pa[l][r][0];
l++;
}
else
{
printf(" %d",r);
va=pa[l][r][1];
r--;
}
}
putchar('\n');
}
return 0;
}
区间dp-zoj3541-The Last Puzzle的更多相关文章
-
Poj 1651 Multiplication Puzzle(区间dp)
Multiplication Puzzle Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10010 Accepted: ...
-
POJ 1651 Multiplication Puzzle(类似矩阵连乘 区间dp)
传送门:http://poj.org/problem?id=1651 Multiplication Puzzle Time Limit: 1000MS Memory Limit: 65536K T ...
-
[ZOJ]3541 Last Puzzle (区间DP)
ZOJ 3541 题目大意:有n个按钮,第i个按钮在按下ti 时间后回自动弹起,每个开关的位置是di,问什么策略按开关可以使所有的开关同时处于按下状态 Description There is one ...
-
区间dp E - Multiplication Puzzle POJ - 1651
E - Multiplication Puzzle POJ - 1651 这个题目没有特别简单,但是也没有我想象之中的那么难,这个题目时区间dp,因为我们是要对区间进行考虑的. 但是呢,这个也和动态 ...
-
POJ1651Multiplication Puzzle(区间DP)
比较好做的区间DP 状态转移方程:DP[i][j] 表示区间[i,j]最小的乘积和. DP[i][j] = MIN{DP[i][k-1]+DP[k+1][j] + a[k]*a[i-1]*a[j+1] ...
-
ZOJ 1602 Multiplication Puzzle(区间DP)题解
题意:n个数字的串,每取出一个数字的代价为该数字和左右的乘积(1.n不能取),问最小代价 思路:dp[i][j]表示把i~j取到只剩 i.j 的最小代价. 代码: #include<set> ...
-
POJ 1651 Multiplication Puzzle (区间DP,经典)
题意: 给出一个序列,共n个正整数,要求将区间[2,n-1]全部删去,只剩下a[1]和a[n],也就是一共需要删除n-2个数字,但是每次只能删除一个数字,且会获得该数字与其旁边两个数字的积的分数,问最 ...
-
POJ 1651:Multiplication Puzzle(区间DP)
http://poj.org/problem?id=1651 题意:给出n个数字,每取中间一个数,就会使得权值加上中间这个数和两边的乘积,求取剩两个数最少的权值是多少. 思路:区间dp. 一开始想了挺 ...
-
HDU5900 QSC and Master(区间DP + 最小费用最大流)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...
-
2016 年沈阳网络赛---QSC and Master(区间DP)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5900 Problem Description Every school has some legend ...
随机推荐
-
[转]Linux df 命令不更新磁盘数据空间使用情况的解决办法
当你已经找出并remove掉Linux系统中的大容量文件时,然后使用df -h查看使用情况依旧不变时.可尝试如下方法解决 1.找出那个进程占用了哪些已删除的文件 # 查看哪些被文件还在被哪个进程占用 ...
-
最短路算法 (bellman-Ford算法)
贝尔曼-福特算法与迪科斯彻算法类似,都以松弛操作为基础,即估计的最短路径值渐渐地被更加准确的值替代,直至得到最优解.在两个算法中,计算时每个边之间的估计距离值都比真实值大,并且被新找到路径的最小长度替 ...
-
PL/SQL查询Oracle数据乱码/Oracle客户端乱码解决办法
[如果此方法都试了就是不行,那么就重复尝试,先把环境变量给删了,注册表里的键值也删除了,然后重启,再配置,肯定行!我试过!] 先确定Oracle服务器采用的是何种编码: select userenv( ...
-
并行编译 Xoreax IncrediBuild
好东西... http://pan.baidu.com/s/1BtZ4s
-
Java经典编程题50道之七
输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. public class Example07 { public static void main(String[] args) ...
-
Web3D
https://baike.baidu.com/item/WEB%203D/11066359?fr=aladdin https://zhidao.baidu.com/question/17325151 ...
-
sklearn CART决策树分类
sklearn CART决策树分类 决策树是一种常用的机器学习方法,可以用于分类和回归.同时,决策树的训练结果非常容易理解,而且对于数据预处理的要求也不是很高. 理论部分 比较经典的决策树是ID3.C ...
-
发起图片请求的几种可能性(webkit内核)
网页测试源代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> &l ...
-
js字符串操作方法
1.字符方法: str.charAt(): 可以访问字符串中特定的字符,可以接受0至字符串长度-1的数字作为参数,返回该位置下的字符,如果参数超出该范围,返回空字符串,如果没有参数,返回位置为0的字符 ...
-
Win8 Pro 64 Install .net3.5 在线升级会遇到错误0x800F0906。
很多人安装Win8后都遇到了无法升级.NET Framework 3.5.1的问题,在线升级会遇到错误0x800F0906. Uninstall Windows update kB: KB296682 ...