【LightOJ 1265】Island of Survival(概率DP)
题目大意:
被拉去参加一个野外求生……姑且这么叫吧。
岛上有t只老虎(T)和d只熊(D)还有自己(M)。每天会有两只生物相遇(自己也算)
T-M T会吃掉M
T-D T会吃掉D
D-D Nothing
M-D M可以选择杀与不杀D
T-T 两只T会互相残杀(Two Die)
问最终人类可以存货的概率(人类存活是指老虎都死光)
自己的思路是遇到熊不杀,这样给存活留有更大的可能。
然后dp转移,最后输出T=0的概率和。
跑了1000+ms
后来看题解,不用考虑熊的任何事情,只管老虎数量就行。仔细想想好像是这样子 = =b 这样跑0ms。。
代码如下:
//1336ms
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <ctime>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 1001;
const int mod = 1e9+7;
const double eps = 1e-8;
double dp[msz][msz];
int main()
{
//fread("");
//fwrite("");
int T,t,d;
scanf("%d",&T);
for(int z = 1; z <= T; ++z)
{
scanf("%d%d",&t,&d);
memset(dp,0,sizeof(dp));
dp[t][d] = 1;
for(int i = t; i >= 0; --i)
{
for(int j = d; j >= 0; --j)
{
int sum = i*j+i*(i-1)/2+i;
if(!sum) continue;
if(j) dp[i][j-1] += dp[i][j]*i*j/sum;
if(i >= 2) dp[i-2][j] += dp[i][j]*i*(i-1)/2/sum;
}
}
double ans = 0;
for(int i = 0; i <= d; ++i)
ans += dp[0][i];
printf("Case %d: %.11f\n",z,ans);
}
return 0;
}
//0ms
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <ctime>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 1001;
const int mod = 1e9+7;
const double eps = 1e-8;
double dp[msz];
int main()
{
//fread("");
//fwrite("");
int T,t,d;
scanf("%d",&T);
for(int z = 1; z <= T; ++z)
{
scanf("%d%d",&t,&d);
memset(dp,0,sizeof(dp));
dp[t] = 1;
for(int i = t; i >= 0; --i)
{
int sum = i*(i-1)/2+i;
if(!sum) continue;
if(i >= 2) dp[i-2] += dp[i]*i*(i-1)/2/sum;
}
printf("Case %d: %.11f\n",z,dp[0]);
}
return 0;
}