ACM 简单DP Pole Arrangement Regionals 2012 >> Asia - Daejeon 区域赛

Pole Arrangement

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=585&page=show_problem&problem=4128

Regionals 2012 >> Asia - Daejeon6117 Pole Arrangement


There are poles of height 1; 2; : : : ; n in a row. If you look at these poles from the left side or the right
side, smaller poles are hidden by taller poles. For example, consider the two arrangements of 4 poles in
the next gure:
For each arrangement, only one pole can be seen from the left, and two poles can be seen from the
right.
You are to write a program to calculate the number of arrangements of n poles such that seen from
the left you see l poles and seen from the right you see r poles.
Input
Your program is to read from standard input. The input consists of T test cases. The number of test
cases T is given in the rst line of the input. Each test case consists of a line containing three integers,
n, l, and r (1 l; r n 20), where n is the number of poles and l (resp. r) is the number of poles
that can be seen from the left (resp. right).
Output
Your program is to write to standard output. Print exactly one line for each test case. The line should
contain the number of arrangements of poles for the test case.
The following shows sample input and output for four test cases.
Sample Input
4
4 1 2
4 1 1
5 2 4
20 2 1
Sample Output
2
0
4
6402373705728000

There are poles of height 1; 2; : : : ; n in a row. If you look at these poles from the left side or the right
side, smaller poles are hidden by taller poles. For example, consider the two arrangements of 4 poles in
the next gure:
For each arrangement, only one pole can be seen from the left, and two poles can be seen from the
right.
You are to write a program to calculate the number of arrangements of n poles such that seen from
the left you see l poles and seen from the right you see r poles.
Input
Your program is to read from standard input. The input consists of T test cases. The number of test
cases T is given in the rst line of the input. Each test case consists of a line containing three integers,
n, l, and r (1 l; r n 20), where n is the number of poles and l (resp. r) is the number of poles
that can be seen from the left (resp. right).
Output
Your program is to write to standard output. Print exactly one line for each test case. The line should
contain the number of arrangements of poles for the test case.
The following shows sample input and output for four test cases.
Sample Input
4
4 1 2
4 1 1
5 2 4
20 2 1
Sample Output
2
0
4

6402373705728000

显然最高的一个杆子,一定是左右都可以看得到的

显然是三维状态DP,两种方法:

1.将新加入的第N个元素当成是最小的,原来n-1个元素变成大一个 

f[i][j][k]=(i-2)*f[i-1][j][k]+f[i-1][j-1][k]+f[i-1][j][k-1];

O(n^3)

2.将新加入的第N个元素当成是最大的,运用枚举左边(右边)的个数,用到组合公式‘

O(n^4)

第一种更优,实现更简单,不要惯性思维


O(n^3)
/*
 * Author: NICK WONG
 * Created Time:  7/27/2014 14:37:52
 * File Name: h.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
#define out(x) cout << #x << x <<endl;
using namespace std;
const double eps(1e-8);
typedef long long LL;
const int maxn=110;
const long long maxint=-1u>>1;
const long long maxlong=maxint*maxint;
long long c[maxn][maxn],f[maxn][maxn][maxn],n,l,r;

void work()
{
    memset(f,0,sizeof(f));
    cin >> n >> l >> r;
    f[1][1][1]=1;
    for (int i=2; i<=n; i++)
        for (int j=1; j<=n; j++)
            for (int k=1; k<=n; k++)
                f[i][j][k]=(i-2)*f[i-1][j][k]+f[i-1][j-1][k]+f[i-1][j][k-1];
    cout << f[n][l][r] << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t--) work(); 
    return 0;
}


O(n^4)
/*
 * Author: NICK WONG
 * Created Time:  7/27/2014 14:37:52
 * File Name: h.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
#define out(x) cout << #x << x <<endl;
using namespace std;
const double eps(1e-8);
typedef long long LL;
const int maxn=110;
const long long maxint=-1u>>1;
const long long maxlong=maxint*maxint;
long long c[maxn][maxn],f[maxn][maxn][maxn];
int n,l,r;

void work()
{
    memset(f,0,sizeof(f));
    cin >> n >> l >> r;
    for (int i=0; i<=20; i++) c[i][0]=1;
    for (int i=1; i<=20; i++)
        for (int j=1; j<=i; j++)
            c[i][j]=c[i-1][j-1]+c[i-1][j];
    /*for (int i=1; i<=20; i++)
        for (int j=1; j<=i; j++)
            if (j==i) cout << c[i][j] << endl; else cout << c[i][j] << " ";*/
    f[0][0][0]=1;
    for (int i=1; i<=n; i++)
    {
        for (int j=1; j<=i; j++)
            for (int k=1; k<=i+1-j; k++)
                for (int x=j-1; x<=i-k; x++)
                    f[i][j][k]+=c[i-1][x]*f[x][j-1][0]*f[i-1-x][0][k-1];
        for (int j=1; j<=i; j++)
            for (int k=1; k<=i+1-j; k++)
            {
                f[i][j][0]+=f[i][j][k];
                f[i][0][k]+=f[i][j][k];
                //out(f[i][j][k]);
            }
    }
    cout << f[n][l][r] << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t--) work(); 
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值