题意:
有n个宝藏,每个都在一个位置p[i],在规定的时间t[i]就会消失。阿里巴巴要在宝藏消失前收集齐所有宝藏,问:有方法吗?有的话最少多少秒?
思路:
开始想的是用状态转移方程来一个个判断,不好写。看了题解知道在一段区间[l,r]要使时间最短必须从端点出来,然后果断写了一个记忆化搜索,tle了。再看题解,所有的递归函数都可以优化成,递推表达式。写了一个递推过了。
线上的动态规划必定要开俩自变量l,r。因为要判断是从l还是r出,加一个自变量p(0:从 l 出 ;1:从 r 出)
可以知道dp[l][r][0]=min (dp[l+1][r][0]+a[l+1]-a[l] , dp[l+1][r][1]+a[r]-a[l]);
dp[i][j][1]=min( dp[i][j-1][1]+a[j]-a[j-1] ,dp[i][j-1][0]+a[j]-a[i]);
这样子递推的循序也出来了
i--,j++;
当dp[l][r][p]>=b[l/r][p]时,将dp[l][r][p]=inf,表示不符合题意;
个人感悟:
刷题就把自己当个逗逼吧!
//tle dfs
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=10000+10;
const int inf=0x3f3f3f3f;
int a[maxn];
int b[maxn];
int dp[maxn][maxn][2];
int dfs(int l,int r,int p)
{
if(dp[l][r][p]!=-1) return dp[l][r][p];
if(r==l)
{
dp[l][r][p]=0;
return 0;
}
if(p==0)
{
//cout<<l<<" "<<r<<endl;
dp[l][r][p]=min(dfs(l+1,r,0)+a[l+1]-a[l] , dfs(l+1,r,1)+a[r]-a[l]);
if(dp[l][r][p]>b[l])
{
dp[l][r][p]=inf;
}
}
else if(p==1)
{
// cout<<l<<" "<<r<<endl;
dp[l][r][p]=min(dfs(l,r-1,0)+a[r]-a[l] , dfs(l,r-1,1)+a[r]-a[r-1]);
if(dp[l][r][p]>b[r])
{
dp[l][r][p]=inf;
}
}
return dp[l][r][p];
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d %d",&a[i],&b[i]);
//cout<<a[i]<<" "<<b[i]<<endl;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dp[i][j][0]=dp[i][j][1]=-1;
}
}
int ans=min(dfs(1,n,0),dfs(1,n,1));
if(ans==inf)
{
printf("No solution\n");
}
else
{
printf("%d\n",ans);
}
}
return 0;
}
//ac 递推
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=10000+10;
const int inf =0x3f3f3f3f;
int a[maxn];
int b[maxn];
int dp[maxn][maxn][2];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d %d",&a[i],&b[i]);
}
// memset(dp,0,sizeof(dp));
for(int i=n;i>0;i--)
{
for(int j=i+1;j<=n;j++)
{
dp[i][j][0]=min( dp[i+1][j][0]+a[i+1]-a[i] , dp[i+1][j][1]+a[j]-a[i]);
if(dp[i][j][0]>=b[i])
{
dp[i][j][0]=inf;
}
dp[i][j][1]=min( dp[i][j-1][1]+a[j]-a[j-1] ,dp[i][j-1][0]+a[j]-a[i]);
if(dp[i][j][1]>=b[j])
{
dp[i][j][1]=inf;
}
}
}
int ans=min(dp[1][n][0],dp[1][n][1]);
if(ans==inf)
{
printf("No solution\n");
}
else
{
printf("%d\n",ans);
}
}
return 0;
}