终于自己能独立切道NOI的题了 (虽说数据很水,随便卡就GG了)
好了好了,CCF的事,能说数据水吗qwq
思路:
一.本来拿到题想的是时不时对每个点排序,然后进行状态转移,维护上凸包,来一发斜率优化,可是我弱呀,不会做这种神仙做法
其实也写了,就是GG了,代码不放上来了,丢人.....
二.后来在写作业的时候偶然发现,好像时间线不是很长,只有1000,是不是可以从这一方面搞一搞呢
于是我的代码就出现了qwq
dp[i][j] 表示 在第i的时间点,j这个位置的烦躁值;
那么 时间线为第一层循环, 位置为第二层循环.
很显然dp方程为
dp[i][j]=min(dp[i][j],dp[q][y]+val(q-p)); (q为这个点所出去的那个点的时间,y为所到的点) 我也说不太清楚呀,大家看代码理解吧
三.上代码咯,qwq
#include<bits/stdc++.h> #define LL long long using namespace std; const int N=2e5+7; const int MN=1e5+7; const int INF=0x7f7f7f7f; int head[N],dp[1010][MN],A,B,C,tim,cnt,n,m; struct edge { int nx,to,p,q; } e[N]; int val(int p,int q) { return A*(q-p)*(q-p)+B*(q-p)+C; } void add_edge(int a,int b,int p,int q) { cnt++;e[cnt].nx=head[a];e[cnt].to=b;e[cnt].p=p;e[cnt].q=q;head[a]=cnt; } int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read(),m=read(),A=read(),B=read(),C=read(); for (int i=1;i<=m;i++) { int x=read(),y=read(),p=read(),q=read(); add_edge(x,y,p,q);tim=max(tim,q); } for (int i=0;i<=tim;i++) for (int j=1;j<=n;j++) dp[i][j]=INF; dp[0][1]=0; for (int i=0;i<=tim;i++) for (int j=1;j<=n;j++) { if (dp[i][j]==INF) continue; for (int k=head[j];k;k=e[k].nx) { int y=e[k].p; if (y<i) continue; dp[e[k].q][e[k].to]=min(dp[e[k].q][e[k].to],dp[i][j]+val(i,e[k].p)); } } int ans=INF; for (int i=1;i<=tim;i++) ans=min(ans,dp[i][n]+i); printf("%d",ans); return 0; }