1 条题解
-
0Guest LV 0 MOD
-
0
考试的时候其实思路大概是正解,写出来怎么也有六十分吧。把数据散列掉,再进行类似于二维背包的操作,并且把所有大于m的数都散列未m。
理想虽丰满,还是爆内存。待到成绩爆零时,钻石丛中笑。
#include<bits/stdc++.h>
const int maxn=31;
inline const void read(int &a)
{
a=0;
char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')
{
a=(a<<1)+(a<<3)+c-'0';
c=getchar();
}
}
inline const void write(int a)
{
if(a>9)write(a/10);
putchar(a%10+'0');
}
int n,m,v[maxn];
double p[maxn],f[2][maxn][50000];
int hash[10000000],ex_hash[50000];
int main()
{
read(n);read(m);
for(int i=1;i<=n;i++)
{
int o;
read(v[i]);read(o);
p[i]=double(o)/100;
}
memset(ex_hash,0,sizeof(ex_hash));
memset(hash,0,sizeof(hash));
memset(f,0,sizeof(f));
int d=-1,x=0;
hash[0]=++d;ex_hash[d]=0;
hash[m]=++d;ex_hash[d]=m;
f[x][0][0]=1;
for(int i=1;i<=n;i++)
{
x^=1;
for(int j=0;j<=i;j++)
for(int k=0;k<=d;k++)
{
int r=ex_hash[k]+v[i];
if(!hash[r])
{
if(r<m){hash[r]=++d;ex_hash[d]=r;}
else r=m;
}
if(j)f[x][j][k]+=f[x^1][j-1][k]*(1.0-p[i]);
f[x][j][hash[r]]+=f[x^1][j][k]*p[i];
}
}
for(int i=0;i<=n;i++)printf("%.3lf\n",f[x][i][hash[m]]);
return 0;
}正解,注意可以bfs,然后在中间合并。原来的复杂度为O(n^30),现在的复杂度为O(2n^15)也就是O(N^16),这就能在一秒以内搜出来了。
#include<cstdio>
#include<cmath>
using namespace std;
double k[40]={0},f[40][40]={0};
int cnt=0,n,m,i,j,v[40],p[40];
int ss(int t,double l,int s,int q)
{
if(s>=m)return 0;
if(t==n+1)
{
if(s<m)f[n][q]-=l;
return 0;
}
ss(t+1,l*p[t]/100.0,s+v[t],q);
ss(t+1,l*(100-p[t])/100.0,s,q+1);
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d%d",&v[i],&p[i]);
f[1][0]=p[1]/100.0;
f[1][1]=(100-p[1])/100.0;
for(i=2;i<=n;i++)
for(j=0;j<=i;j++)
{
if(j)f[i][j]+=f[i-1][j-1]*(100-p[i])/100.0;
f[i][j]+=f[i-1][j]*(p[i]/100.0);
}
ss(1,1,0,0);
for(i=0;i<=n;i++)
printf("%.3lf\n",f[n][i]);
return 0;
}
- 1
信息
- 难度
- 9
- 分类
- (无)
- 标签
- (无)
- 递交数
- 3
- 已通过
- 1
- 通过率
- 33%
- 上传者