洛谷 P1850 换教室(期望dp)
传送门
解题思路
用dp[i][j][0/1]表示到第i节课、申请了j次,第i节课是否申请的最小体力和。
然后分别从dp[i-1][j][0]、dp[i-1][j][1],dp[i-1][j-1][0]、dp[i-1][j-1][1]疯狂转移过来。
先跑一边Floyd求最短路。
注意double无法用memset初始化。
具体看代码吧。
比较易懂。
AC代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<iomanip> 12 #include<ctime> 13 #include<stack> 14 using namespace std; 15 int dis[305][305],n,m,v,e,c[2005],d[2005]; 16 double dp[2005][2005][2],k[2005],ans=1000000; 17 int main() 18 { 19 cin>>n>>m>>v>>e; 20 for(int i=1;i<=v;i++){ 21 for(int j=1;j<=v;j++){ 22 dis[i][j]=1000000; 23 } 24 } 25 for(int i=1;i<=v;i++) dis[i][i]=0; 26 for(int i=1;i<=n;i++) cin>>c[i]; 27 for(int i=1;i<=n;i++) cin>>d[i]; 28 for(int i=1;i<=n;i++) cin>>k[i]; 29 for(int i=1;i<=e;i++){ 30 int u,v,value; 31 cin>>u>>v>>value; 32 dis[u][v]=min(dis[u][v],value); 33 dis[v][u]=min(dis[v][u],value); 34 } 35 for(int kk=1;kk<=v;kk++){ 36 for(int i=1;i<=v;i++){ 37 for(int j=1;j<=v;j++){ 38 dis[i][j]=min(dis[i][j],dis[i][kk]+dis[kk][j]); 39 } 40 } 41 } 42 for(int i=1;i<=n;i++){ 43 for(int j=0;j<=m;j++){ 44 dp[i][j][0]=dp[i][j][1]=1000000; 45 } 46 } 47 dp[1][0][0]=dp[1][1][1]=0; 48 for(int i=2;i<=n;i++){ 49 dp[i][0][0]=dp[i-1][0][0]+dis[c[i]][c[i-1]]; 50 for(int j=1;j<=min(i,m);j++){ 51 dp[i][j][0]=min(dp[i-1][j][0]+dis[c[i]][c[i-1]],dp[i-1][j][1]+k[i-1]*dis[c[i]][d[i-1]]+(1-k[i-1])*dis[c[i]][c[i-1]]); 52 dp[i][j][1]=min(dp[i-1][j-1][0]+dis[c[i]][c[i-1]]*(1-k[i])+dis[d[i]][c[i-1]]*k[i],dp[i-1][j-1][1]+dis[c[i]][c[i-1]]*(1-k[i])*(1-k[i-1])+dis[c[i]][d[i-1]]*(1-k[i])*k[i-1]+dis[d[i]][c[i-1]]*k[i]*(1-k[i-1])+dis[d[i]][d[i-1]]*k[i]*k[i-1]); 53 } 54 } 55 for(int i=0;i<=min(n,m);i++){ 56 ans=min(ans,min(dp[n][i][0],dp[n][i][1])); 57 } 58 printf("%.2lf",ans); 59 return 0; 60 }
//NOIP2016提高组 Day1 t3