UVALive 5695 -The Last Puzzle -区间dp
2016-09-29 00:53
471 查看
http://bak.vjudge.net/problem/UVALive-5695
题意:一排开关,要把所有开关全部按下的步骤,移动距离=时间,给出每个开关的位置,并且每个开关按下后经过一定的时间ti又会弹起来,求出一个合法步骤,没有则输出imp
区间dp:
得先想到一个东西: 对于区间[i,j]如果有解,那么最优解(即所花时间最短)的方案的起始点一定是在区间的端点(左端点或右端点)。
因为如果选中间开始,最后假设先经过左端点,以后必然要经过右端点,而此时必然经过位于中间的起点。
有了这个性质,就很好转移了
dp[i][j][0] 表示先按最左边时的最小时间代价
dp[i][j][1]为先按右边
显然:
dp[i][j][0]=min(dp[i+1][j][0]+d[i+1]-d[i], dp[i+1][j][1]+d[j]-d[i] );
dp[i][j][1]=min(dp[i][j-1][0] +d[j]-d[i], dp[i][j-1][1]+d[j]-d[j-1] );
n^2的dp,
用一个path记录下当前状态最优值是由哪个子状态的来的。
如果dp[i][j][0/1]超过了起点的持久时间,则该方案不可行,置为无穷大
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
typedef long long ll;
const int N=200+50;
const ll inf=1e18;
ll dp
[2];
int path
[2];
int t
,d
;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for (int i=1; i<=n; i++) scanf("%d",&t[i]);
for (int i=1; i<=n; i++) scanf("%d",&d[i]);
memset(dp,0,sizeof dp);
for (int len=2; len<=n; len++)
{
for (int i=1; i+len-1<=n; i++)
{
int j=i+len-1;
int left=0;
int right=0;
dp[i][j][0]=min(dp[i+1][j][0]+d[i+1]-d[i], dp[i+1][j][1]+d[j]-d[i] );
dp[i][j][1]=min(dp[i][j-1][0] +d[j]-d[i], dp[i][j-1][1]+d[j]-d[j-1] );
if (dp[i+1][j][0]+d[i+1]-d[i] == dp[i][j][0])
path[i][j][0]=0;
else
path[i][j][0]=1;
if (dp[i][j-1][0] +d[j]-d[i]==dp[i][j][1])
path[i][j][1]=0;
else path[i][j][1]=1;
if (t[i]<=dp[i][j][0]) dp[i][j][0]=inf;
if (t[j]<=dp[i][j][1]) dp[i][j][1]=inf;
}
}
int l=1,r=n,f=233;
if (dp[1]
[0]<inf)
{
f=path[1]
[0];
printf("%d",l++);
}
else if (dp[1]
[1]<inf)
{
f=path[1]
[1];
printf("%d",r--);
}
else
{
printf("Mission Impossible\n");
continue;
}
while(l<=r)
{
if (f==0)
{
f=path[l][r][0];
printf(" %d",l++);
}
else
{
f=path[l][r][1];
printf(" %d",r--);
}
}
printf("\n");
}
return 0;
}
题意:一排开关,要把所有开关全部按下的步骤,移动距离=时间,给出每个开关的位置,并且每个开关按下后经过一定的时间ti又会弹起来,求出一个合法步骤,没有则输出imp
区间dp:
得先想到一个东西: 对于区间[i,j]如果有解,那么最优解(即所花时间最短)的方案的起始点一定是在区间的端点(左端点或右端点)。
因为如果选中间开始,最后假设先经过左端点,以后必然要经过右端点,而此时必然经过位于中间的起点。
有了这个性质,就很好转移了
dp[i][j][0] 表示先按最左边时的最小时间代价
dp[i][j][1]为先按右边
显然:
dp[i][j][0]=min(dp[i+1][j][0]+d[i+1]-d[i], dp[i+1][j][1]+d[j]-d[i] );
dp[i][j][1]=min(dp[i][j-1][0] +d[j]-d[i], dp[i][j-1][1]+d[j]-d[j-1] );
n^2的dp,
用一个path记录下当前状态最优值是由哪个子状态的来的。
如果dp[i][j][0/1]超过了起点的持久时间,则该方案不可行,置为无穷大
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
typedef long long ll;
const int N=200+50;
const ll inf=1e18;
ll dp
[2];
int path
[2];
int t
,d
;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for (int i=1; i<=n; i++) scanf("%d",&t[i]);
for (int i=1; i<=n; i++) scanf("%d",&d[i]);
memset(dp,0,sizeof dp);
for (int len=2; len<=n; len++)
{
for (int i=1; i+len-1<=n; i++)
{
int j=i+len-1;
int left=0;
int right=0;
dp[i][j][0]=min(dp[i+1][j][0]+d[i+1]-d[i], dp[i+1][j][1]+d[j]-d[i] );
dp[i][j][1]=min(dp[i][j-1][0] +d[j]-d[i], dp[i][j-1][1]+d[j]-d[j-1] );
if (dp[i+1][j][0]+d[i+1]-d[i] == dp[i][j][0])
path[i][j][0]=0;
else
path[i][j][0]=1;
if (dp[i][j-1][0] +d[j]-d[i]==dp[i][j][1])
path[i][j][1]=0;
else path[i][j][1]=1;
if (t[i]<=dp[i][j][0]) dp[i][j][0]=inf;
if (t[j]<=dp[i][j][1]) dp[i][j][1]=inf;
}
}
int l=1,r=n,f=233;
if (dp[1]
[0]<inf)
{
f=path[1]
[0];
printf("%d",l++);
}
else if (dp[1]
[1]<inf)
{
f=path[1]
[1];
printf("%d",r--);
}
else
{
printf("Mission Impossible\n");
continue;
}
while(l<=r)
{
if (f==0)
{
f=path[l][r][0];
printf(" %d",l++);
}
else
{
f=path[l][r][1];
printf(" %d",r--);
}
}
printf("\n");
}
return 0;
}
相关文章推荐
- ZOJ 3541 The Last Puzzle(经典区间dp)
- ZOJ 3541-The Last Puzzle(区间DP)
- ZOJ3541-The Last Puzzle 区间dp
- ZOJ 3541 - The Last Puzzle(区间dp)
- 区间dp-zoj3541-The Last Puzzle
- HDU 4053 or ZOJ 3541 The Last Puzzle 区间dp
- ZOJ3541:The Last Puzzle(区间DP)
- Zoj 3541 The Last Puzzle(区间dp)
- UVa 10688 The Poor Giant(区间DP)
- UVALive - 2728 A Spy in the Metro DP
- uvalive 3363(区间dp)
- UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)
- uva 10688 - The Poor Giant(区间DP,较难,题目难懂,状态转移难。。。)
- uva 10688 - The Poor Giant(区间dp)
- UVALIVE 6301 The Shortcut Eight-Puzzle
- UVA 10688 The Poor Giant (区间DP)
- HDU 2476 | UVALive 4394 - String painter (区间DP)
- UVALive6662 The Last Ant
- UVAlive 6560 - The Urge to Merge(状压dp)
- UVALive - 3363 String Compression (区间DP)