首页 > 代码库 > 【uoj262】 NOIP2016—换教室
【uoj262】 NOIP2016—换教室
http://uoj.ac/problem/262 (题目链接)
题意
有${n}$个时间段,第${i}$个时间段可以选择在${c_i}$教室上课,也可以选择申请换课,有${k_i}$概率申请通过,在${d_i}$上课,另外${1-k_i}$的概率留在${c_i}$教室。 总共有${v}$个教室,${e}$条路径双向联通教室${x_i}$和${y_i}$,路径有权值${w_i}$。在课间时(相邻两个时间段的间隔中),你要从上一个教室走最短路径到下一个教室。 现在你有${m}$次申请机会,只能提前申请一堆换课(也就是你不能在知道某一次申请结果后再去申请下一个换课)。求总距离的最小期望。
Solution
跟去年那道子串好像啊。。
先floyd算出图中两两点之间的距离,然后dp。
用${f[i][j]}$表示上到第${i}$堂课,已经申请了${j}$次,并且第${i}$堂课的教室被申请,所花费的总体力。
用${g[i][j]}$表示上到第${i}$堂课,已经申请了${j}$次,并且第${i}$堂课的教室没有被申请,所花费的总体力。
转移很显然$${f[i][j]=Min(f[i-1][j-1]+dis,g[i-1][j-1]+dis)}$$
$${g[i][j]=Min(f[i-1][j]+dis,g[i-1][j]+dis)}$$
细节
注意Floyd的总点数是V(好像坑了好多人)。
代码
// uoj262#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#define inf 2147483640#define LL long long#define Pi acos(-1.0)#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)using namespace std;const int maxn=2010;int n,m,E,V;int c[maxn],d[maxn];double dis[maxn][maxn],K[maxn],f[maxn][maxn],g[maxn][maxn];void Floyd() { for (int k=1;k<=V;k++) for (int i=1;i<=V;i++) for (int j=1;j<=V;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);}void dp() { for (int i=1;i<=n;i++) for (int j=0;j<=m;j++) f[i][j]=g[i][j]=inf; g[1][0]=f[1][1]=0; for (int i=2;i<=n;i++) for (int j=0;j<=min(i,m);j++) { if (j) { f[i][j]=f[i-1][j-1]+K[i-1]*K[i]*dis[d[i-1]][d[i]]; f[i][j]+=K[i-1]*(1-K[i])*dis[d[i-1]][c[i]]; f[i][j]+=(1-K[i-1])*K[i]*dis[c[i-1]][d[i]]; f[i][j]+=(1-K[i-1])*(1-K[i])*dis[c[i-1]][c[i]]; f[i][j]=min(f[i][j],g[i-1][j-1]+K[i]*dis[c[i-1]][d[i]]+(1-K[i])*dis[c[i-1]][c[i]]); } g[i][j]=min(f[i-1][j]+K[i-1]*dis[d[i-1]][c[i]]+(1-K[i-1])*dis[c[i-1]][c[i]],g[i-1][j]+dis[c[i-1]][c[i]]); }}int main() { scanf("%d%d%d%d",&n,&m,&V,&E); for (int i=1;i<=n;i++) scanf("%d",&c[i]); for (int i=1;i<=n;i++) scanf("%d",&d[i]); for (int i=1;i<=n;i++) scanf("%lf",&K[i]); for (int i=1;i<=V;i++) { for (int j=1;j<=V;j++) dis[i][j]=inf; dis[i][i]=0; } for (int u,v,w,i=1;i<=E;i++) { scanf("%d%d%d",&u,&v,&w); dis[u][v]=min(dis[u][v],(double)w); dis[v][u]=min(dis[v][u],(double)w); } Floyd(); dp(); double ans=inf; for (int i=0;i<=m;i++) ans=min(ans,min(f[n][i],g[n][i])); printf("%.2lf",ans); return 0;}
【uoj262】 NOIP2016—换教室
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。