题意:给定n个轮盘,轮盘有pi个数字,花费ci元转它,等概率停在某个数字,你将获得该数字的积分
求达到m积分的最小期望值
思路:定义dp[i]表示已经得到积分i,为达到m积分的最小花费,
枚举转盘,再枚举转盘的数字,对应后继状态,
若转盘为2,4,6,8则dp[i]=ci+(1/4)*dp[i+2]+(1/4)*dp[i+4]+(1/4)*dp[i+6]+(1/4)*dp[i+8]
同时消除0,若为0,4,6,8则dp[i]=ci+(1/4)*dp[i]+(1/4)*dp[i+4]+(1/4)*dp[i+6]+(1/4)*dp[i+8]移项的dp[i]=(4/3)*c[i]+(1/3)*dp[i+4]+(1/3)*dp[i+6]+(1/3)*dp[i+8]
int n,m;
vector<int>v[N];
double c[N];
double dp[N];
void solve(){
cin>>n>>m;
fr(i,1,n){
cin>>c[i];
int x;
cin>>x;
int cnt=0;
fr(j,1,x){
int y;
cin>>y;
if(y==0){
cnt++;
}
else{
v[i].push_back(y);
}
}
c[i]=1.0*c[i]*x/(x-cnt);
}
ufr(i,m-1,0){
double ans=inf;
fr(j,1,n){
double t=0;
for(auto k:v[j]){
t+=(i+k>=m?0:dp[i+k])+c[j];
}
t/=v[j].size();
ans=min(ans,t);
}
dp[i]=ans;
}
printf("%.10lf",dp[0]);
}
signed main()
{
int t=1;
// cin>>t;
while(t--) solve();
return 0;
}
规律:
1.两数相减,相加的最大,最小值
2.由最初的状态递推
3.无强制顺序,排序
4.对于一段等差数列,不用一段一段的算局部整体,可以从整体一步步加差值
5.需要从一段式子推到结果困难,将结果反推式子,(从结果的需要特性式子需要全部满足)
6.式子移项。式子消去
7.将一步步走到结果,反推到能走到这个结果一定会存在什么步骤
8.枚举两个位置,当一个位置可由另一个位置一个条件推出时,一个位置即可
9.删边最小=加边最大
10.隔板法:C(m-1,n-1),
11.统计区间的值,当前状态取决于上一个状态与当前值,dp[当前位置][结果可能]=数量
12.一个后面情况全由第一个决定,枚举第一个所有情况
13.分类,一共有少数个类别,由少数个类别组成的多个数,分类
14.一个数的改变对前面有影响或对后面有影响
算法
1.点到线段的最短距离公式
2.bfs求最短路(在n*m的图上,套用spfa板子)
3.树的深度
4.bitset优化
5.dp二维,一维位置,二维所有可能结果
6.取石子的sg函数打表
7.带权并查集的关系维护,并查集(子树合并:节点数)
8.基环内向树(特点:从任意一个点出发,必定会跑到环内)
9.最短路或最长路分层图的建立,路径上最大值最小(边权传递),相遇问题:枚举相遇点+反向最短路
10.最小生成树:每个结点多个选择,多建多个源点与之相连
11.记忆化
12.树状数组+离散化维护区间移项
13.期望dp
14.sg打表,sg函数(拿l~r)