1. 程式人生 > >2018年10月30日提高組 T2 B

2018年10月30日提高組 T2 B

大意

一個長度為nn的數軸,有kk種移動方式,切換移動方式需要花費ww的代價,第ii種方法花費viv_i的代價使你移動did_i格,然後有QQ個限制,即不能用bjb_j號移動方式經過第aja_j格,求最小代價。

思路

這是一種最優化問題,考慮dpdpbfsbfs,本人用的是dpdp

f[i][j]f[i][j]表示前ii個格子,目前使用第jj種移動方式,得到當之前移動方式相同時

f[i][j]=f[idj][j]+vjf[i][j]=f[i-d_j][j]+v_j

當移動方式不同時

f[i][j]=f[idj][l]+vj+wf[i][j]=f[i-d_j][l]+v_j+w

邊界,當i==dji==d_j

f[i][j]=vjf[i][j]=v_j

程式碼

#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;int n,k,w,f[501][101],qg[101],dj[101],xz,ans=0x3f3f3f3f,a,b;
bool cant[101][501];
inline
int read() { char c;int f=0,d=1; while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48; while(c=getchar(),c>47&&c<58) f=(f<<3)+(f<<1)+c-48; return d*f; } signed main() { memset(f,0x3f3f3f3f,sizeof(f)); n=read();k=read();w=read(); for(register
int i=1;i<=k;i++) qg[i]=read(),dj[i]=read(); xz=read(); while(xz--) { a=read();b=read(); for(register int i=a;i<=min(a+qg[b],n);i++) cant[b][i]=true; } memset(f[0],0,sizeof(f[0])); for(register int i=1;i<=n;i++) for(register int j=1;j<=k;j++) { if(cant[j][i]) continue; if(i<qg[j]) continue; if(i==qg[j]) f[i][j]=min(dj[j],f[i][j]); f[i][j]=min(f[i-qg[j]][j]+dj[j],f[i][j]);//動態轉移 for(register int l=1;l<=k;l++) if(l!=j) f[i][j]=min(f[i-qg[j]][l]+dj[j]+w,f[i][j]);//動態轉移 } for(register int i=1;i<=k;i++) ans=min(ans,f[n][i]);//取最優解 if(ans<502345678) printf("%d",ans); else puts("-1"); }