一道挺有意思的动态规划题目

idler 2001-09-20 02:20:15
Consider an ordered set S of strings of N (1 <= N <= 31) bits. Bits, of course, are either 0 or 1.

This set of strings is interesting because it is ordered and contains all possible strings of length N that have L (1 <= L <= N) or fewer bits that are `1'.

Your task is to read a number I (1 <= I <= sizeof(S)) from the input and print the Ith element of the ordered set for N bits with no more than L bits that are `1'.

PROGRAM NAME: kimbits
INPUT FORMAT
A single line with three space separated integers: N, L, and I.
SAMPLE INPUT (file kimbits.in)
5 3 19

OUTPUT FORMAT
A single line containing the integer that represents the Ith element from the order set, as described.
SAMPLE OUTPUT (file kimbits.out)
10011
...全文
107 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
mathe 2001-09-22
  • 打赏
  • 举报
回复
Sorry, I have pasted a debug version
#include <stdio.h>

#ifdef _DEBUG
#include <assert.h>
#define ASSERT(x) assert(x)
#else
#define ASSERT(x)
#endif

int CountNL[31][31];
int Pascal[31];

void InitPascal()
{
int i=0;
Pascal[0]=1;
CountNL[0][0]=1;
for(i=0;i<30;i++)
{
int j;
Pascal[i+1]=1;
for(j=i;j>0;j--)
{
Pascal[j]+=Pascal[j-1];
}
CountNL[i+1][0]=Pascal[0];
for(j=1;j<=i+1;j++)
{
CountNL[i+1][j]=CountNL[i+1][j-1]+Pascal[j];
}
}
}

int ReadNumberI(int I,int L)
{
int N=31;
int x,y;
ASSERT(N>=L+1);
InitPascal();
if(I==1)
return 0;
I--;
L++;
while(N>=1&&CountNL[N-1][L-1]>I)
{
N--;
if(L>N)L=N;
}
x=1<<(N-1);
y=CountNL[N-1][L-1];
while(y<I)
{
L--;
N--;
while(N>=1&&CountNL[N-1][L-1]>I-y)
{
N--;
if(L>N)L=N;
}
x+=1<<(N-1);
y+=CountNL[N-1][L-1];
ASSERT(N>=0||y<I);
}
return x;
}

int main()
{
int N,L,I,r,t;
scanf("%d%d%d",&N,&L,&I);
r=ReadNumberI(I,L);
{
int n=N;
while(n>0)
{
if(r&(1<<--n))
printf("1");
else
printf("0");
}
}
printf("\n");
return 0;
}
mathe 2001-09-22
  • 打赏
  • 举报
回复
#include <stdio.h>

#ifdef _DEBUG
#include <assert.h>
#define ASSERT(x) assert(x)
#else
#define ASSERT(x)
#endif

int CountNL[31][31];
int Pascal[31];

void InitPascal()
{
int i=0;
Pascal[0]=1;
CountNL[0][0]=1;
for(i=0;i<30;i++)
{
int j;
Pascal[i+1]=1;
for(j=i;j>0;j--)
{
Pascal[j]+=Pascal[j-1];
}
CountNL[i+1][0]=Pascal[0];
for(j=1;j<=i+1;j++)
{
CountNL[i+1][j]=CountNL[i+1][j-1]+Pascal[j];
}
}
}

int ReadNumberI(int I,int L)
{
int N=31;
int x,y;
ASSERT(N>=L+1);
InitPascal();
if(I==1)
return 0;
I--;
L++;
while(N>=1&&CountNL[N-1][L-1]>I)
{
N--;
if(L>N)L=N;
}
x=1<<(N-1);
y=CountNL[N-1][L-1];
while(y<I)
{
L--;
N--;
while(N>=1&&CountNL[N-1][L-1]>I-y)
{
N--;
if(L>N)L=N;
}
x+=1<<(N-1);
y+=CountNL[N-1][L-1];
ASSERT(N>=0||y<I);
}
return x;
}

int main()
{
int N,L,I,r,t;
scanf("%d%d%d",&N,&L,&I);
for(t=1;t<=I;t++)
{
r=ReadNumberI(t,L);
{
int n=N;
while(n>0)
{
if(r&(1<<--n))
printf("1");
else
printf("0");
}
}
printf("\n");
}
return 0;
}
idler 2001-09-22
  • 打赏
  • 举报
回复
怎么没人做啊?!
starfish 2001-09-20
  • 打赏
  • 举报
回复
呵呵,今天下午就要参加数学建模竞赛了,没时间做这道题目了,等我回来后再做吧。
idler 2001-09-20
  • 打赏
  • 举报
回复
这里是全部测试数据:
------- test 1 -------
4 2 1
------- test 2 -------
1 1 2
------- test 3 -------
8 4 30
------- test 4 -------
10 2 56
------- test 5 -------
7 7 64
------- test 6 -------
18 3 300
------- test 7 -------
21 10 1048576
------- test 8 -------
24 20 12936478
------- test 9 -------
31 24 10000000
------- test 10 -------
31 31 2147483648
------- test 11 -------
31 26 12345678
------- test 12 -------
31 26 123456789
------- test 13 -------
31 26 1234567890
----------------------
idler 2001-09-20
  • 打赏
  • 举报
回复
中文意思就是:
给定N,L,I,找出所有长度为N,最多含有L个1,第I大的二进制串(允许类似00000之类的有前导0的串)

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧