[hdu4418]Time travel
Time travel
题解
无论如何,这题面是真的难理解
如果我们用来表示从点
走到点
的期望步数的话,我们很容易得到一个方程
。
由于这种逆推式不能转化为状态转移方程式来dp求解,我们只能用高斯消元来对其进行求解。
于是,可以得到方程式。再用高斯消元进行求解。
可是,它可以向两个方向走,我们就把原来的数列再往后翻折一半,将变成
。
之后再通过bfs求出可达的点,如果终点不可达就直接输出,否则,再此基础上建出期望方程,解出来输出的值即可。
注意需特判起点与终点是否不同,否则会因的情况RE。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
typedef long long LL;
const double INF=1e9;
const double eps=1e-9;
int n,m,N,M,X,Y,D,tot;
double arr[305][305],ans[305],p[305];
bool frecnt[305];
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
void swap1(int x,int y,int len){for(int i=0;i<=len;i++)swap(arr[x][i],arr[y][i]);}
bool Zero(double x){return Fabs(x)>eps;}
int gauss(){
int t=0,p=0;
/*for(int i=0;i<m;i++){
for(int j=0;j<=n;j++)
printf("%lf ",arr[i][j]);
puts("");
}*/
for(;p<m&&t<m;p++,t++){
int maxx=p;
for(int j=p+1;j<m;j++)
if(Fabs(arr[j][t])>Fabs(arr[maxx][t]))
maxx=j;
if(p!=maxx)swap1(p,maxx,n);
if(Fabs(arr[p][t])<eps){p--;continue;}
for(int j=p+1;j<m;j++){
if(Fabs(arr[j][t])<eps)continue;
double tmp=arr[j][t]/arr[p][t];
for(int k=t;k<=n;k++)
arr[j][k]-=arr[p][k]*tmp;
}
}
for(int i=p;i<m;i++)if(Fabs(arr[i][t])>eps)return -1;
if(p<m){
int num=0,freidx;
for(int i=p-1;i>=0;i--){
num=0;double tmp=arr[i][n];
for(int j=0;j<n;j++)
if(Fabs(arr[i][j])>eps&&frecnt[j])
num++,freidx=j;
if(num>1)continue;tmp=arr[i][n];
for(int j=0;j<n;j++)
if(Fabs(arr[i][j])>eps&&j!=freidx)
tmp-=arr[i][j]*ans[j];
ans[freidx]=tmp/arr[i][freidx];frecnt[freidx]=0;
}
return m-p;
}
for(int i=m-1;i>=0;i--){
double tmp=arr[i][n];
for(int j=i+1;j<n;j++)
tmp-=arr[i][j]*ans[j];
ans[i]=tmp/arr[i][i];
}
return 0;
}
bool vis[305];
queue<int> q;
void bfs(int s){
while(!q.empty())q.pop();
q.push(s);vis[s]=1;
while(!q.empty()){
int t=q.front();q.pop();
for(int i=1;i<=M;i++){
int v=(t+i)%N;
if(Zero(p[i])&&!vis[v])
q.push(v),vis[v]=1;
}
}
}
signed main(){
int t;scanf("%d",&t);
while(t--){
memset(arr,0,sizeof(arr));
memset(ans,0,sizeof(ans));
memset(vis,0,sizeof(vis));
memset(frecnt,1,sizeof(frecnt));double sum=0;
scanf("%d %d %d %d %d",&N,&M,&Y,&X,&D);
for(int i=1;i<=M;i++)scanf("%lf",&p[i]),p[i]/=100.0,sum+=1.0*i*p[i];
if(X==Y){puts("0.00");continue;}
N=2*(N-1);n=m=N;if(D>0)X=(N-X)%N;bfs(X);
if(!vis[Y]&&!vis[(N-Y)%N]){puts("Impossible !");continue;}
for(int i=0;i<N;i++){
arr[i][i]=1;
if(!vis[i]){arr[i][N]=INF;continue;}
if(i==Y||i==(N-Y)%N){arr[i][N]=0;continue;}
arr[i][N]=sum;int now=i;
for(int j=1;j<=M;j++){
now++;if(now==N)now=0;
arr[i][now]-=p[j];
}
}
int fc=gauss();
if(fc<0)puts("Impossible !");
else printf("%.2lf\n",ans[X]);
}
return 0;
}

浙公网安备 33010602011771号