[dp][前缀和] Jzoj P5907 轻功(qinggong)
题解
- 数据这么小,各位大爷肯定都会做吧
- 考虑dp,设f[i][j]为走到第i个木桩,现在是用第j中轻功的最小时间
- 状态转移方程显然
- 那么,考虑一下题目的条件,有一些限制木桩不能用某些轻功经过
- 可以设g[i][j]为用j轻功到i有多少个没有的经过的木桩
- 剩下的平平常常都能A吧
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 const long long inf=0x3f3f3f3f3f3f; 6 int n,k,w,a[510],v[510],Q,g[510][110]; 7 long long f[510][110],ans; 8 int main() 9 { 10 //freopen("qinggong.in","r",stdin); 11 //freopen("qinggong.out","w",stdout); 12 scanf("%d%d%d",&n,&k,&w); 13 for (int i=1;i<=k;i++) scanf("%d%d",&a[i],&v[i]); 14 scanf("%d",&Q); 15 for (int i=1,x,y;i<=Q;i++) scanf("%d%d",&x,&y),g[x][y]=1; 16 for (int i=1;i<=k;i++) 17 for (int j=1;j<=n;j++) 18 g[j][i]+=g[j-1][i]; 19 memset(f,125,sizeof(f)); 20 for (int i=1;i<=k;i++) f[0][i]=0; 21 for (int i=0;i<=n;i++) 22 for (int j=1;j<=k;j++) 23 for (int z=1;z<=k;z++) 24 if (i+a[z]<=n&&(g[i+a[z]][z]-g[i][z]==0)) 25 { 26 if (j==z) f[i+a[z]][z]=min(f[i+a[z]][z],f[i][j]+v[z]); 27 else f[i+a[z]][z]=min(f[i+a[z]][z],f[i][j]+v[z]+w); 28 } 29 ans=inf; 30 for (int i=1;i<=k;i++) ans=min(ans,f[n][i]); 31 printf("%lld",ans==inf?-1:ans); 32 }