您的位置:首页 > Web前端

POJ1037A decorative fence(动态规划+排序计数+好题)

2015-12-22 11:42 302 查看
http://poj.org/problem?id=1037

题意:输入木棒的个数n,其中每个木棒长度等于对应的编号,把木棒按照波浪形排序,然后输出第c个;

分析:总数为i跟木棒中第k短的木棒 就等于总数为i-1中比这一根短的方案数 + 和比这一根长的方案数;最后用一个三维数组表示成c[i][k][up/down],c[i][k][up]表示i跟木棒中第k短的下一个比他长的方案数,就可以枚举每一个比他长的数相加;

排列计数问题:求一个排列中第几个是什么?

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
#define UP 0
#define DOWN 1
const int MAX = 30;
long long c[MAX][MAX][2];
int seq[MAX],used[MAX];
void Init(int n)
{
memset(c, 0, sizeof(c));
c[1][1][UP] = c[1][1][DOWN] = 1;
for(int i = 2; i <= n; i++)  //个数
{
for(int k = 1; k <= i; k++)  //第i短
{
for(int N = k; N < i; N++)
{
//这个循环为什么k而不是k+1开始呢?
//因为c[i][k][UP]是指以i个木棒中第k短开头的上升木棒,那么下一个的总数就是i-1,那是i-1中第几短呢,除掉前面的那个k,比他长的就是第k到i-1(除去k后,比他稍微长点的就成了第k短)
c[i][k][UP] +=  c[i - 1]
[DOWN];
}
for(int M = 1; M <= k - 1; M++)
{
//这个没啥影响
c[i][k][DOWN] += c[i - 1][M][UP];
}
}
}
}
void print(int n, long long cc)
{
long long  skipped = 0;
int No = 0;
long long  oldValue = skipped;
memset(used, 0, sizeof(used));
for(int i = 1; i <= n; i++)
{
int k;
No = 0;
oldValue = skipped;
for(k = 1; k <= n; k++)
{
oldValue = skipped;//用oldvalue保留每一次最先开始的次数,然后skipped不断算跳跃的方案数
if(used[k] == 0)
{
No++;
if(i == 1)
{
skipped += c
[No][UP] + c
[No][DOWN];
}
else
{
if(k > seq[i - 1] && (i <= 2 || seq[i - 2] > seq[i - 1]))
{
skipped += c[n - i + 1][No][DOWN];
}
else if(k < seq[i - 1] && (i <= 2 || seq[i - 2] < seq[i - 1]))
{
skipped += c[n - i + 1][No][UP];
}
}
if(skipped >= cc) //跳跃的方案数比给定的大,那就跳出循环,如果比cc小就在改变oldvalue值
break;
}
}
used[k] = true;
seq[i] = k;
skipped = oldValue;
}
for(int i = 1; i < n; i++)
printf("%d ", seq[i]);
printf("%d\n", seq
);
}
int main()
{
int t,n;
long long C;
Init(20);
scanf("%d", &t);
while(t--)
{
scanf("%d%I64d", &n,&C);
print(n, C);
}
return 0;
}


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