T1
无环图,直接
dp
d
p
转移即可,从终点往起点转移
由于这道题的数据水,不用考虑无法到达n的路径
#include<bits/stdc++.h>
using namespace std;
int n , m;
int linkk[101000] , t;
int chu[101000];
bool vis[101000];
struct node{
int n , y , v;
}e[401000];
double dp[101000];
int read(){
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void insert(int x,int y,int z){
e[++t].y = y;e[t].n = linkk[x];e[t].v = z;chu[x]++;linkk[x] = t;
return;
}
void init(){
n = read();m = read();
for(int i = 1;i <= m;++i){
int x = read() , y = read() , z = read();
insert( x , y , z );
}
return;
}
void Dp(int x){
vis[x] = true;
if(x == n){
dp[x] = 0;
return;
}
for(int i = linkk[x];i;i = e[i].n){
int y = e[i].y;
if(!vis[y]) Dp(y);
dp[x] = dp[x] + dp[y] + e[i].v;
}
if(chu[x])dp[x] /= chu[x];
return;
}
int main(){
freopen("tour.in","r",stdin);
freopen("tour.out","w",stdout);
init();
Dp(1);
printf("%.2lf",dp[1]);
return 0;
}
T2
f[i][j]
f
[
i
]
[
j
]
表示剩余
i
i
行列没有灯的状态到目标状态所需的期望
令
p[i]
p
[
i
]
表示行(或列)已经点亮了
i
i
行(列),下一次点到所需的行(列)的概率
这样就可以写出状态转移方程
f[i][j]=(f[i−1][j]+1)∗p[i]∗(1−p[j])
f
[
i
]
[
j
]
=
(
f
[
i
−
1
]
[
j
]
+
1
)
∗
p
[
i
]
∗
(
1
−
p
[
j
]
)
+(f[i][j−1]+1)∗(1−p[i])∗p[j]
+
(
f
[
i
]
[
j
−
1
]
+
1
)
∗
(
1
−
p
[
i
]
)
∗
p
[
j
]
+(f[i−1][j−1]+1)∗p[i]∗p[j]
+
(
f
[
i
−
1
]
[
j
−
1
]
+
1
)
∗
p
[
i
]
∗
p
[
j
]
+(f[i][j]+1)∗(1−p[i])∗(1−p[j])
+
(
f
[
i
]
[
j
]
+
1
)
∗
(
1
−
p
[
i
]
)
∗
(
1
−
p
[
j
]
)
将最后一项包括
f[i][j]
f
[
i
]
[
j
]
的拆开,移项即可求解
#include<bits/stdc++.h>
using namespace std;
double dp[2010][2010];
double p[2010] ;
bool f[2010][2010];
bool xxx[2010] , yyy[2010];
int X , Y;
int n , m;
int read(){
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void init(){
n = read();int k = read();
for(int i = 1;i <= k;++i){
int x = read() , y = read();
xxx[x] = true;yyy[y] = true;
}
for(int i = 1;i <= n;++i)
p[i] = i * 1.0 / n;
return;
}
void Dp(int x,int y){
if( x < 0 || y < 0 ){
f[x][y] = true;
return;
}
if( x > 0 && !f[x - 1][y] )
Dp(x - 1 , y);
if( x > 0 )
dp[x][y] = dp[x][y] + (dp[x - 1][y] + 1) * p[x] * (1 - p[y]);
if( y > 0 && !f[x][y - 1] )
Dp(x , y - 1);
if( y > 0 )
dp[x][y] = dp[x][y] + (dp[x][y - 1] + 1) * (1 - p[x]) * p[y];
if( x > 0 && y > 0 && !f[x - 1][y - 1] )
Dp(x - 1 , y - 1);
if(x > 0 && y > 0)
dp[x][y] = dp[x][y] + (dp[x - 1][y - 1] + 1) * p[x] * p[y];
dp[x][y] += (1 - p[x]) * (1 - p[y]);
dp[x][y] = dp[x][y] / ( 1 - (1 - p[x]) * (1 - p[y]));
f[x][y] = 1;
return;
}
void work(){
X = 0 , Y = 0;
for(int i = 1;i <= n;++i)
if(!xxx[i]) X++;
for(int i = 1;i <= n;++i)
if(!yyy[i]) Y++;
dp[0][0] = 0; f[0][0] = true;
if(!f[X][Y]) Dp(X,Y);
printf("%.6lf",dp[X][Y]);
return;
}
int main(){
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
init();
work();
return 0;
}
T3
传送门:https://blog.csdn.net/a1035719430/article/details/80991529
#include<bits/stdc++.h>
using namespace std;
int n , m;
double p[3010][310] , f[310][3010];
double g[3010] , g_lazy[310] , tmp[3010];
double ans;
int num[310];
int read(){
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void pre(){
n = read();m = read();
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
p[i][j] = read() * 1.0 / 1000;
for(int j = 1;j <= m;++j)
f[j][0] = 1.0;
for(int i = 1;i <= m;++i){
for(int j = 1;j <= n;++j)
f[i][j] = f[i][j - 1] * ( 1 - p[j][i]);
g_lazy[i] = 1.0 - f[i][n];
}
return;
}
void solve(int x){
num[x]++;
if(num[x] >= n){
g_lazy[x] = 0;
return;
}
for(int i = 0;i <= n;++i)
tmp[i] = f[x][i];
f[x][0] = 0.0;
for(int i = 1;i <= n;++i)
f[x][i] = f[x][i - 1] * (1.0 - p[i][x]) + tmp[i - 1] * p[i][x];
g_lazy[x] -= f[x][n];
return;
}
void work(){
for(int i = 1;i <= n;++i){
double Max = 0 ;int id = 0;
for(int j = 1;j <= m;++j)
if( Max < g_lazy[j] ){
Max = g_lazy[j];
id = j;
}
ans += Max;
if(!id) return;
solve(id);
}
printf("%.8lf",ans);
return;
}
int main(){
freopen("gift.in","r",stdin);
freopen("gift.out","w",stdout);
pre();
work();
return 0;
}