码迷,mamicode.com
首页 > 其他好文 > 详细

USACO Section 3.2 01串 Stringsobits

时间:2016-07-25 13:07:57      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:

题目背景

考虑排好序的N(N<=31)位二进制数。

题目描述

他们是排列好的,而且包含所有长度为N且这个二进制数中1的位数的个数小于等于L(L<=N)的数。

你的任务是输出第i(1<=i<=长度为N的二进制数的个数)小的(注:题目这里表述不清,实际是,从最小的往大的数,数到第i个符合条件的,这个意思),长度为N,且1的位数的个数小于等于L的那个二进制数。

(例:100101中,N=6,含有位数为1的个数为3)。

输入输出格式

输入格式:

共一行,用空格分开的三个整数N,L,i。

输出格式:

共一行,输出满足条件的第i小的二进制数。

 

最容易想到的方法就是模拟,从0开始利用位移判断枚举的这个数二进制中1的个数是否符合限制,会有一半TLE

 1 #include<iostream>
 2 using namespace std;
 3 int N,L,i,ans=0;
 4 bool Judge(int x)
 5 {
 6   int count=0;
 7   for(int j=0;j<N;j++)
 8     if(x&(1<<j)) count++;
 9   return count<=L;
10 }
11 void PrintAns()
12 {
13   for(int j=N-1;j>=0;j--)
14     if(ans&(1<<j)) cout<<1;
15     else cout<<0;
16 }
17 int main()
18 {
19   cin>>N>>L>>i;
20   for(int j=1;j<=i;j++)
21     while(!Judge(ans++));
22   ans--;
23   PrintAns();
24   return 0;
25 }

正确做法是动态规划

设dp(len,count)代表长度len,1的限制为count时的方案数

从左到右判断每一位是0or1 具体看代码

还有一点!如果N,L,i的数据类型变成int而不是unsigned int就会卡一个点(这坑爹的数据)

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int v[33][33],mem[33][33];
 5 unsigned int N,L,i;
 6 int dp(int len,int count){
 7     int& ans=mem[len][count];
 8     if(v[len][count]) return ans;
 9     v[len][count]=1;
10     if(count==0||len==0) return ans=1;
11     return ans=dp(len-1,count)+dp(len-1,count-1);
12 }
13 int main()
14 {
15   memset(v,0,sizeof(v));
16   cin>>N>>L>>i;
17   for(int j=N-1;j>=0;j--){
18     if(dp(j,L)<i){
19       cout<<1;
20       i-=dp(j,L);
21         L--;//确定这一位是1后,1的限制要-1
22     }else{
23       cout<<0;
24     }
25   }
26   return 0;
27 }

From Linux

USACO Section 3.2 01串 Stringsobits

标签:

原文地址:http://www.cnblogs.com/gzhonghui/p/5703038.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!