最长上升子序列
for
,所以慢。最大子段和
最长公共子序列
for
就可以了,先从前一个位置转移,然后相同就加$1$,不相同不处理,一直传下去。最后一个就是答案。分析:(上次写过这道题(SP64))那道题和这道题不一样的,这道题还带一个前缀和优化。可以发现,朴素的做法是 $O(nk^2)$ 的,在这道题的数据会超时。然后又会发现,第 3 层循环的作用就是把 $f[i][...]$ 加起来,所以说可以想到前缀和的做法。详情见题解。
还有,记得要取模!
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 1e3+5;
const int Mod = 1e4;
int n, k, f[MAXN][MAXN];
int main() {
scanf ("%d%d",&n,&k);
f[1][0]=1;
for (int i=2; i<=n; i++) {
int sum = 0;
for (int j=0; j<=k; j++) {
sum += f[i-1][j];
sum %= Mod;
f[i][j]=sum;
if ( j-i+1 >= 0 ) {
sum = ( sum-f[i-1][j-i+1]+Mod )%Mod;
}
}
}
printf ("%d\n",f[n][k]);
return 0;
}
分析:懒得写了(根本不会),$Sooke$的题解。然后老师$PPT$上列了一个转移方程:(雾)
$$ f_{i,j}=\max\limits_{k \in[0,maxP],t \in[0,i-w]}(f_{t,k}+sell_-or_-buy(i,j-k)) $$
时间复杂度:$O(n^3)$
分析:发现这道题让你添加括号就是改变合并顺序,所以想到区间$dp$,区间$dp$最经典的题就是石子合并,这题也是只让你合并相邻的两个,计算最小代价。
分析:这题挺冷的,没什么人做,看到数据范围就可以先想到用“暴力”了,这题算的全是概率,所以什么时候加,什么时候乘不要搞错了,前面有个轮空规则不要忘了(应该不会吧$qwq$),然后差不多就是一个接近于模拟的一个$dp$。众所周知,$dp$可以使用任何方法,递归也是可以的,就像上次学校考试中的$T5$,$std$使用的就是$dfs$(递归)$+dp$。
$Code$:
#include <cstdio>
#include <iostream>
using namespace std;
double data[16][11],b[6][6],win[6][6][6],f[3][7][7][7];
int t,n;
double ans=0,tot=0;
bool book[16];
void dfs(int p) {
if(p>5) {
f[0][1][1][1]=f[1][1][1][1]=f[2][1][1][1]=1.0/3.0;
for(int i=1; i<=6; i++) {
for(int j=1; j<=6; j++) {
for(int k=1; k<=6; k++) {
if(i>1) {
f[0][i][j][k]=f[1][i-1][j][k]*win[4][k][i-1]+f[2][i-1][j][k]*win[2][j][i-1];
if(i==6)
f[0][i][j][k]+=f[0][i][j-1][k]*win[5][k][j-1]+f[0][i][j][k-1]*win[3][j][k-1];
}
if(j>1) {
f[1][i][j][k]=f[0][i][j-1][k]*win[5][k][j-1]+f[2][i][j-1][k]*win[0][i][j-1];
if(j==6)
f[1][i][j][k]+=f[1][i-1][j][k]*win[4][k][i-1]+f[1][i][j][k-1]*win[1][i][k-1];
}
if(k>1) {
f[2][i][j][k]=f[0][i][j][k-1]*win[3][j][k-1]+f[1][i][j][k-1]*win[1][i][k-1];
if(k==6)
f[2][i][j][k]+=f[2][i-1][j][k]*win[2][j][i-1]+f[2][i][j-1][k]*win[0][i][j-1];
}
}
}
}
tot=0;
for(int i=1; i<=5; i++) {
tot+=f[1][i][6][6];
}
ans=max(ans,tot);
return;
}
int l,r;
for(l=1; l<=n; l++) {
if(!book[l]) {
book[l]=true;
for(r=1; r<=5; r++) {
win[0][p][r]=data[l][r];
win[2][r][p]=1.0-data[l][r];
}
for(r=1; r<=5; r++) {
win[1][p][r]=data[l][r+5];
win[4][r][p]=1.0-data[l][r+5];
}
dfs(p+1);
book[l]=false;
}
}
return;
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++)
for(int j=1; j<=10; j++)
scanf("%lf",&data[i][j]);
for(int i=1; i<=5; i++) {
for(int j=1; j<=5; j++) {
scanf("%lf",&b[i][j]);
win[3][i][j]=b[i][j];
win[5][j][i]=1.0-b[i][j];
}
}
dfs(1);
printf("%.6lf\n",ans);
return 0;
}
本文作者:Snowflake_Pink
本文链接:https://snowflake.pink/archives/69/
最后修改时间:2020-04-13 11:32:39
本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!