求助DP qwq
查看原帖
求助DP qwq
230804
Durancer楼主2021/4/18 20:17

思路是这样的:

fi,j,0/1f_{i,j,0/1} 表示处理完第 ii 个点到第 jj 个点后,停在 ii 点(0) ,或者停在 jj 点的位置时花费的最小值。

转移方程是:

fi,j,0=min{fi+1,j,0+(posi+1posi)v×Δfi+1,j,1+(posjposi)v×Δf_{i,j,0}=\operatorname{min}\begin{cases}f_{i+1,j,0}+\frac{(pos_{i+1}-pos_{i})}{v}\times Δ \\ \\f_{i+1,j,1}+\frac{(pos_{j}-pos_{i})}{v}\times Δ \end{cases}

fi,j,1=min{fi,j1,0+(posjposi)v×Δfi,j1,1+(posjposj1)v×Δf_{i,j,1}=\operatorname{min}\begin{cases}f_{i,j-1,0}+\frac{(pos_{j}-pos_{i})}{v}\times Δ \\ \\f_{i,j-1,1}+\frac{(pos_{j}-pos_{j-1})}{v}\times Δ \end{cases}

处理操作是把初始位置点也加进去,然后按照位置大小排序后进行区间DP。样例已过,但不知道哪里错了qwq,求大佬查错

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const double INF=0x3f3f3f3f;
const int N=1e3+9;
const int M=1e3+9;
struct node{
	double pos;//位置 
	double delt;//增长量 
	double once;//立刻修复的花费 
}wal[N];
double sum[N];//前缀和 
double tol;//一开始的总的立刻修理的花费 
double v;//速度 
int n,c;
double f[N][N][3];//修理完i-j区间停在了i(0)j(1)时的最小费用 
int read()
{
	int f=1,x=0;
	char s=getchar();
	while(s<'0'||s>'9')
	{
		if(s=='-')	
			f=-1;
		s=getchar();
	}
	while(s>='0'&&s<='9')
	{
		x=(x<<1)+(x<<3)+(s^'0');
		s=getchar(); 
	}
	return f*x;
}
bool cmp(node x,node y)
{
	return x.pos<y.pos;
}
void prepare()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			f[i][j][1]=f[i][j][0]=INF;//赋极大值 
	int now=0;
	for(int i=1;i<=n;i++)
		if(wal[i].pos==(double)c&&wal[i].once==0&&wal[i].delt==0)
		{
			now=i;
			break;
		}//找出起始点的位置; 
	for(int i=1;i<=n;i++)
		tol+=wal[i].once; //直接把一开始的花费存到一起 
	f[now][now][1]=0;
	f[now][now][0]=0;//预处理起始点 
	for(int i=1;i<=n;i++)
		sum[i]=sum[i-1]+wal[i].delt;//前缀和 
}
void DP()
{
	for(int len=2;len<=n;len++)
		for(int i=1;i-1+len<=n;i++)
		{
			int j=i-1+len;
			f[i][j][0]=min(f[i+1][j][0]+(wal[i+1].pos-wal[i].pos)/v*(sum[n]-sum[j]+sum[i]),
						   f[i+1][j][1]+(wal[j].pos-wal[i].pos)/v*(sum[n]-sum[j]+sum[i]));
			f[i][j][1]=min(f[i][j-1][1]+(wal[j].pos-wal[j-1].pos)/v*(sum[n]-sum[j-1]+sum[i-1]),
						   f[i][j-1][0]+(wal[j].pos-wal[i].pos)/v*(sum[n]-sum[j-1]+sum[i-1]));
//			printf("f[%d][%d][0]= %lf\n",i,j,f[i][j][0]);
//			printf("f[%d][%d][1]= %lf\n",i,j,f[i][j][1]);	
		}
	return;
}
int main()
{
	while(cin>>n)
	{
		scanf("%lf",&v);
		//cout<<"v= "<<v<<endl;
		c=read();
		if(n==0) break;	
		for(int i=1;i<=n;i++)
			scanf("%lf%lf%lf",&wal[i].pos,&wal[i].once,&wal[i].delt);	
		wal[++n].pos=double(c);//把起始点加进去 
		wal[n].once=0.0;
		wal[n].delt=0.0;
		sort(wal+1,wal+1+n,cmp);
		prepare(); 
		DP();
		printf("%d\n",(int)tol+min((int)f[1][n][0],(int)f[1][n][1]));
	} 
	return 0;
}
2021/4/18 20:17
加载中...