【spoj Favorite Dice && 洛谷p4550】
spoj的是简单版
洛谷的是稍复杂版
区别是复杂版在简单版的基础上多做了一次期望dp
也可以用期望的平方理解 但还不会…
链接分别如下:
spoj简单版.
洛谷复杂版.
下面先贴代码 有时间再来补解析:
#include<bits/stdc++.h>
#define maxn 10005
using namespace std;
double dp[maxn],ans[maxn];
/*----------洛谷p4550 && spoj Favorite Dice-------------*\
dp[n-i] 表示n-i个出现过, 直到取完还需的期望次数
ans[n-i] 表示n-i个出现过,直到取完还需的期望花费
转移方程 如下
dp[n-i]=(n-i)/n*dp[n-i]+i/n*dp[n-i+1]+1
ans[n-i]=(n-i)/n*ans[n-i]+i/n*ans[n-i+1]+dp[n-i]
移项后即是代码中的转移方程
\*------------------------------------------------------*/
int main()
{
int n;
scanf("%d",&n);
dp[n]=0,ans[n]=0;
for(int i=1;i<=n;i++){
dp[n-i]=dp[n-i+1]+1.0*n/i;
ans[n-i]=ans[n-i+1]+dp[n-i]*n/i;
}
printf("%.2lf\n",ans[0]);
return 0;
}
【Robots 2019 ACM-ICPC 南京赛区网络赛 D】
题意:对于一个DAG(有向无环图),每天在一个节点上有等可能的机会选择走到下一个节点或者不动,花费的代价时当前的天数,发现与上题类似,也是一个天数一个花费,且花费为天数,因此采用类似的dp两次的思路。
代码如下:(感谢学长帮忙写的拓扑)
#include<bits/stdc++.h>
#define ll long long
#define mem(b,t) memset(b,t,sizeof(b))
#define INF 0x3f3f3f3f
#define rep(i,n,m) for(int i=n;i<=m;i++)
#define per(i,n,m) for(int i=n;i>=m;i--)
#define bug1(i) cout<<i<<endl
#define bug2(i,j) cout<<i<<" "<<j<<endl
#define maxn 100005
#define mod 1000000007
using namespace std;
struct TPSORT{
int n;
vector<int> G[maxn];
int d[maxn];
double dp1[maxn],dp2[maxn];
//dp1[i] 表示从i到终点期望的天数
//dp2[i] 表示从i到终点期望的花费
int dd[maxn];
void init(int _n){
n=_n;
for(int i=1;i<=n;++i) G[i].clear(), dp1[i]=dp2[i]=0;
}
void addedge(int u, int v){
G[u].push_back(v);
}
//拓扑排序1
void work1(){
queue<int> q;
dp1[n]=-1;
for(int i=1;i<=n;++i) // cal du
for(int v:G[i]) d[v]++;
for(int i=1;i<=n;++i) dd[i]=d[i];
for(int i=1;i<=n;++i) if(!d[i]) q.push(i); // push start
while(q.size()){
int u=q.front(); q.pop();
dp1[u]++;
if(dd[u])
dp1[u]=dp1[u]*(dd[u]+1.0)/dd[u];
for(int v:G[u]){
dp1[v]+=1.0*dp1[u]/(dd[v]+1);
if(!(--d[v])) q.push(v);
}
}
}
//拓扑排序2
void work2(){
queue<int> q;
dp2[n]=-dp1[n];
for(int i=1;i<=n;++i) // cal du
for(int v:G[i]) d[v]++;
for(int i=1;i<=n;++i) dd[i]=d[i];
for(int i=1;i<=n;++i) if(!d[i]) q.push(i); // push start
while(q.size()){
int u=q.front(); q.pop();
dp2[u]+=dp1[u];
if(dd[u])
dp2[u]=dp2[u]*(dd[u]+1.0)/dd[u];
for(int v:G[u]){
dp2[v]+=1.0*dp2[u]/(dd[v]+1);
if(!(--d[v])) q.push(v);
}
}
}
}TpSort;
int main(){
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
TpSort.init(n);
while(m--){
int x,y;
cin>>x>>y;
TpSort.addedge(y,x);
}
TpSort.work1();
TpSort.work2();
printf("%.2lf\n",TpSort.dp2[1]);
}
return 0;
}
【Table Tennis 2020 ICPC Asia Taiwan】
#include<bits/stdc++.h>
#define ll long long
#define mem(b,t) memset(b,t,sizeof(b))
#define INF 0x3f3f3f3f
#define rep(i,n,m) for(int i=n;i<=m;i++)
#define per(i,n,m) for(int i=n;i>=m;i--)
#define bug1(i) cout<<i<<endl
#define bug2(i,j) cout<<i<<" "<<j<<endl
#define maxn 1005
#define db double
#define eps 1e-6
#define pi acos(-1)
using namespace std;
double dp[maxn][maxn];
double ans1,ans2,ans;
void cal(int n){
double t;
rep(i,1,n-2){
rep(j,i+1,n-1){
rep(k,j+1,n){
if(n%2==1) t=ans2;
else t=ans1;
if(i%2==1) t*=ans1;
else t*=ans2;
if(j%2==1) t*=ans1;
else t*=ans2;
if(k%2==1) t*=ans1;
else t*=ans2;
rep(p,1,n){
if(p!=i&&p!=j&&p!=k){
if(p%2==1) t*=(1-ans1);
else t*=(1-ans2);
}
}
ans+=t;
}
}
}
}
int main(){
int n;
scanf("%d",&n);
while(n--){
rep(i,0,1000)
rep(j,0,1000)
dp[i][j]=0;
double p1,p2;
ans=0,ans1=0,ans2=0;
scanf("%lf %lf",&p1,&p2);
dp[0][0]=1;
rep(i,0,1000){
rep(j,0,1000){
if(!dp[i][j]) continue;
int tot=i+j;
if(max(i,j)>=11 && abs(j-i)>1){
if(i>j) ans1+=dp[i][j];
continue;
}
tot++;
double p;
if(tot<=20){
if((tot-1)%4/2==1) p=1-p2;
else p=p1;
}
else {
if(tot%2==1) p=p1;
else p=1-p2;
}
dp[i+1][j]+=dp[i][j]*p;
dp[i][j+1]+=dp[i][j]*(1-p);
}
}
// cout<<ans1<<endl;
rep(i,0,1000)
rep(j,0,1000)
dp[i][j]=0;
dp[0][0]=1;
rep(i,0,1000){
rep(j,0,1000){
if(!dp[i][j]) continue;
int tot=i+j;
double t=dp[i][j];
if(max(i,j)>=11 && abs(j-i)>1){
if(i>j) ans2+=dp[i][j];
continue;
}
tot++;
double p;
if(tot<=20){
if((tot-1)%4/2==1) p=p1;
else p=1-p2;
}
else {
if(tot%2==1) p=1-p2;
else p=p1;
}
dp[i+1][j]+=dp[i][j]*p;
dp[i][j+1]+=dp[i][j]*(1-p);
}
}
// cout<<ans2<<endl;
rep(i,3,6){
cal(i);
}
printf("%.10lf\n",ans);
}
return 0;
}
/*
4
0.25 0.75
0.5 0.5
0.4 0.6
0.75 0.25
*/