您的位置:首页 > 其它

poj3934解题报告

2015-06-14 23:44 706 查看
题目大意:n个小朋友排队(每个小朋友都不一样高)。两个小朋友a和b能够互相看见当且仅当排在它们中间的小朋友比a和b都要矮。已知队伍中一共有m对小朋友可以互相看见,问有可能有多少种排队方式。

思路:应该拿DP来做,一开始我还想拿递归生成全排列,剪枝呢~~后来看了别人思路真的绝了

那个人的思路大概是这样:

状态变量d[i][j]表示i个人,j个对一共有多少种方式

然后对于每一种i个人组成j对的状态有两种决策:

1.(i-1)个人先组成(j-2)对,然后最矮的人插在彼此的间隙中,此时不会对原来的对数造成任何影响(因为这是最矮的)

if(j>=2)

d[i][j]=(d[i-1][j-2]*(i-2))%9937; //中间有i-2个空可以让他插

2.(i-1)个人先组成(m-1)对,然后最矮的人照在两侧,此时也不会对原来的对数产生任何影响,而且只增加了一对。

(d[i][j]+d[i-1][j-1]*2) // 一首一尾两种情况

所以状态方程:

if(j>=2)

d[i][j]=(d[i-1][j-2]*(i-2))%9937;

if(j>=1)

d[i][j]=(d[i][j]+d[i-1][j-1]*2)%9937;

边界自己想吧 ~~

#include<cstdio>

#include<algorithm>

#include<iostream>

#include<cstring>

using namespace std;

int main()

{

int n,m,d[85][10100];

memset(d,0,sizeof(d));

d[1][0]=1;

d[2][1]=2;

for(int i=3;i<=80;i++)

for(int j=0;j<=10000;j++)

{

if(j>=2)

d[i][j]=(d[i-1][j-2]*(i-2))%9937;

if(j>=1)

d[i][j]=(d[i][j]+d[i-1][j-1]*2)%9937;

}

while(cin>>n>>m)

{

if(n==0&&m==0) break;

cout<<d
[m]<<endl;

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: