洛谷:P1220 关路灯(提高+/省选-,dp)

题目:

在这里插入图片描述

分析:这个区间有意思,表示区间外的。

做的过程中想到了紫书上的小偷上地铁题,三维数组。

不过根据这个题,我将三维数组的第三位只取0,1.因为每次一定在最边上。

自己想的,自己写的。感觉很好!,哪有问题检查不出来?就这吧,懒得看答案。

代码:

#include<bits/stdc++.h>
using namespace std;
int A[60][2]; 
int D[60][60][2];//0处于x位置,1处于y位置。 
int m,n;
long long f(int x,int y,int z,int t)
{//从x到y的已经算了,包含x,y 
 if(D[x][y][z]!=-1) return D[x][y][z];
 if(x==0&&y==m-1) return 0;
 if(x==0&&z==0)
 {
  D[x][y][z]=f(x,y,1,t+A[y][0]-A[x][0]);
  if(x==y) D[x][y][0]=D[x][y][1]=D[x][y][z];
  return D[x][y][z];
 }
 if(x==0&&z==1)
 {
  D[x][y][z]=f(x,y+1,1,t+A[y+1][0]-A[y][0])+(t+A[y+1][0]-A[y][0])*A[y+1][1];
  if(x==y) D[x][y][0]=D[x][y][1]=D[x][y][z];
  return D[x][y][z];
 }
 if(y==m-1&&z==1)
 {
  D[x][y][z]=f(x,y,0,t+A[y][0]-A[x][0]);
  if(x==y) D[x][y][0]=D[x][y][1]=D[x][y][z];
  return D[x][y][z];
 }
 if(y==m-1&&z==0)
 {
  D[x][y][z]=f(x-1,y,0,t+A[x][0]-A[x-1][0])+(t+A[x][0]-A[x-1][0])*A[x-1][1];
  if(x==y) D[x][y][0]=D[x][y][1]=D[x][y][z];
  return D[x][y][z];
 }
 D[x][y][z]=1<<30;
 if(z==0)
 D[x][y][z]=min((A[x][0]-A[x-1][0])*A[x-1][1]+f(x-1,y,0,t+(A[x][0]-A[x-1][0])),(A[y+1][0]-A[x][0])*A[y+1][1]+f(x,y+1,1,t+(A[y+1][0]-A[x][0])));
 if(z==1)
 D[x][y][z]=min((A[y][0]-A[x-1][0])*A[x-1][1]+f(x-1,y,0,t+(A[y][0]-A[x-1][0])),(A[y+1][0]-A[y][0])*A[y+1][1]+f(x,y+1,1,t+(A[y+1][0]-A[y][0])));
 if(x==y) D[x][y][0]=D[x][y][1]=D[x][y][z];
 return D[x][y][z];
}  
int main()
{
 cin>>m>>n;
 for(int i=0;i<m;i++) cin>>A[i][0]>>A[i][1];
 memset(D,-1,sizeof(D));
 if(n<A[0][0]) 
 {
  cout<<(A[0][0]-n)*A[0][1]+f(0,0,1,A[0][0]-n);
  return 0;
 }
 if(n>A[m-1][0])
 {
  cout<<(-A[m-1][0]+n)*A[m-1][1]+f(m-1,m-1,0,-A[m-1][0]+n); return 0;
  }
 for(int i=0;i<m;i++)
 {
  if(A[i][0]==n)
  {
   cout<<min(f(i,i,0,1),f(i,i,1,1)); return 0;
  }
  if(A[i][0]>n)
  {
   cout<<min(f(i-1,i-1,0,n-A[i-1][0])+(n-A[i-1][0])*A[i-1][1],f(i,i,0,A[i][0]-n)+(A[i][0]-n)*A[i][1]);
   return 0;
   }  
 }
}

猜你喜欢

转载自blog.csdn.net/weixin_42721412/article/details/107579957