UVALive - 5695 The Last Puzzle (思维+区间dp)

题目链接

题目大意:有n个按钮排成一条直线,你的任务是通过左右移动按下所有按钮,按钮如果一段时间没有被按下就会被弹开。

以下是我的推论(不一定正确)

直观地看的话,如果选择的是最优路径,那么路径的形状必然是若干条区域逐渐缩小的折线,如图所示:

而不可能出现这个样子:

因为,如果这样走的话,那么中间从A到B一段反复经过的区域就全都浪费了,不如直接从C走到D划算。

进一步观察可以发现,每一个按钮只有最后一次被按下的时候是有效的,因此答案序列应当是一个从两边向中间聚合的过程。

设dp[L][R][f]表示当前在区间[L,R]的左端点(f=0)或右端点(f=1),将区间[L,R]中的所有按钮全部按下所需的最短时间,每一步只有两种选择:

1.按下当前按钮并往前走一步,以后就都不管这个按钮了,此时$dp[L][R][0]=min(dp[L][R][0],dp[L+1][R][0])+dis[L+1]-dis[L]) $(以左端点为例,右端点类似,下同。dis[i]表示i点与左端点的距离)

2.跑到对面去准备按下对面的按钮,此时$dp[L][R][0]=min(dp[L][R][0],dp[L][R][1])+dis[R]-dis[L]) $

总复杂度$O(n^2)$

吐槽:ZOJ凉了,HDU后台有问题过不了,只能交到UVAlive上了,QAQ

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=200+10,inf=0x3f3f3f3f;
 5 int dp[N][N][2],op[N][N][2],n,t[N],dis[N];
 6 int dfs(int L,int R,int f) {
 7     int& ret=dp[L][R][f],&opp=op[L][R][f];
 8     if(~ret)return ret;
 9     if(L==R)return ret=0;
10     ret=inf;
11     if(f==0) {
12         int x=dfs(L+1,R,0)+dis[L+1]-dis[L];
13         int y=dfs(L,R,1)+dis[R]-dis[L];
14         if(x<t[L]&&x<ret)ret=x,opp=0;
15         if(y<ret)ret=y,opp=1;
16     } else {
17         int x=dfs(L,R-1,1)+dis[R]-dis[R-1];
18         int y=dfs(L,R,0)+dis[R]-dis[L];
19         if(x<t[R]&&x<ret)ret=x,opp=0;
20         if(y<ret)ret=y,opp=1;
21     }
22     return ret;
23 }
24 vector<int> ans;
25 void pr(int L,int R,int f) {
26     if(L==R) {ans.push_back(L); return;}
27     int opp=op[L][R][f];
28     if(opp==0) {
29         if(f==0)ans.push_back(L),pr(L+1,R,f);
30         else ans.push_back(R),pr(L,R-1,f);
31     } else pr(L,R,f^1);
32 }
33 int main() {
34     while(scanf("%d",&n)==1) {
35         for(int i=1; i<=n; ++i)scanf("%d",&t[i]);
36         for(int i=1; i<=n; ++i)scanf("%d",&dis[i]);
37         memset(dp,-1,sizeof dp);
38         int x=dfs(1,n,0),y=dfs(1,n,1);
39         if(x==inf&&y==inf)puts("Mission Impossible");
40         else {
41             ans.clear();
42             if(x<=y)pr(1,n,0);
43             else pr(1,n,1);
44             for(int i=0; i<ans.size(); ++i)printf("%d%c",ans[i]," \n"[i==ans.size()-1]);
45         }
46     }
47     return 0;
48 }

 

posted @ 2019-08-19 21:01  jrltx  阅读(234)  评论(0编辑  收藏  举报