USACO Stringsobits, 还是得搬出动态规划来
来源:互联网 发布:8月份上海房产成交数据 编辑:程序博客网 时间:2024/04/30 20:25
这题证明俺现在真是老了,退步了,这是第一份代码:
- #include <fstream>
- using namespace std;
- ifstream fin("kimbits.in");
- ofstream fout("kimbits.out");
- unsigned int N, L, pos;
- int main()
- {
- fin >> N >> L >> pos;
- unsigned int num = 0, count = 0, max = (1<<N)-1, bit1, tmp;
- while(count < pos)
- {
- if(num > max) break;
- bit1 = 0, tmp = num;
- for(; tmp > 0; bit1++)
- tmp &= (tmp - 1);
- if(bit1 <= L) ++count;
- ++num;
- }
- num -- ;
- for (int i = N-1; i >=0; --i)
- fout << ((num >>i) & 0x1u);
- fout << endl;
- return 0;
- }
其实还是挺简洁的哈,就是会超时,因为基本思路是暴力搜索。
这个是很郁闷的,看数据,确实太大了。仔细端详一番,觉得有DP的感觉,例如,对于(二进制)二位数:10 11,要得到三位数,实际上就是移位和移位+1,+1的操作中可以判断+1后得到的数字中的1是不是超过了给定的L,不过,首先还是先崩溃了一下:
- #include <fstream>
- #include <deque>
- #include <vector>
- using namespace std;
- ifstream fin("kimbits.in");
- ofstream fout("kimbits.out");
- typedef unsigned int UINT;
- UINT N, L, pos;
- vector<deque<UINT> > dp;
- inline int printBinary(UINT num)
- {
- for (int i = N-1; i >=0; --i)
- fout << ((num >>i) & 0x1u);
- fout << endl;
- return 0;
- }
- int main()
- {
- fin >> N >> L >> pos;
- if(pos <= 2) {
- printBinary(pos-1);
- return 0;
- }
- deque<UINT> d, dPre;
- d.push_back(0);
- for(UINT i = 0; i <= N; ++i)
- dp.push_back(d);
- dp[0][0] = 1, dp[0].push_back(1);
- UINT count = 2, uTmp;
- for(UINT i = 0; i < N; ++i)
- {
- for(UINT k = 0; k <= i; ++k)
- {
- d.clear();
- for(UINT j = 1; j <= dp[k][0]; ++j)
- {
- uTmp = (dp[k][j] << 1);
- if(++count == pos) return printBinary(uTmp);
- if(k+2 <= L) // k从0开始的
- {
- uTmp = (dp[k][j]<<1)+1;
- if(++count == pos) return printBinary(uTmp);
- d.push_back(uTmp);
- }
- dp[k][j] <<= 1;
- }
- if(k == i)
- {
- dp[k+1].insert(++dp[k+1].begin(), d.begin(), d.end());
- dp[k+1][0] += d.size();
- }
- if(k > 0)
- {
- dp[k].insert(++dp[k].begin(), dPre.begin(), dPre.end());
- dp[k][0] += dPre.size();
- }
- dPre = d;
- }
- }
- return 0;
- }
时间还不知道,空间先扛不住了:
看Test 6和7,估计这个办法也不咋滴,为什么呢,究其原因还是无效计算过多。下面是AC的代码,主要算法思想写在注释里了,这道题本来很简单的,却搞了我这么久,受打击了,呜呜....
- #include <fstream>
- using namespace std;
- typedef unsigned int UINT;
- ifstream fin("kimbits.in");
- ofstream fout("kimbits.out");
- UINT N, L, pos;
- UINT dp[33][33]; // dp(i,j)表示长度为i,1的个数不超过j的串有多少
- int res[33]={0};
- int main()
- {
- fin>> N >> L >> pos;
- for(UINT j = 0; j <= L; j++)
- dp[0][j] = 1;
- // 方程:f[j,k]=f[j-1,k]+f[j-1,k-1]; 分别表示在当前位加上0和加上1时的两种状况
- // 边界:f[j,0]=1, f[0,j]=1, f[j,k](k>j)=f[j,j]
- // 这样我们得到了所有的f[j,k] 需要做的就是据此构造出所求字符串
- for(UINT i = 0; i <= N; i++)
- {
- for(UINT j = 0; j <=L; j++)
- {
- if(j == 0) dp[i][j] = 1;
- else if(j <= i) dp[i][j] = dp[i-1][j] + dp[i-1][j-1];
- else if(j > i) dp[i][j] = dp[i][i];
- }
- }
- // 构造思路如下:
- // 设所求串为S,假设S的位中最高位的1在K位
- // 那么必然满足:
- // F[K-1,L]<pos and F[K,L]>=pos
- // 这样的K是唯一的, 所以S的第一个1在从右至左第K位
- // 因为有F[K-1,L]个串第K位上为0,所以所求的第I个数的后K位就应该是:
- // 满足"位数为K且串中1不超过L-1个"这个条件的第 pos - F[K,L] 个数 => 递归的过程
- while(pos > 1)
- {
- for(int i = N-1; i>=0; i--)
- {
- if(dp[i][L] < pos)
- {
- res[N-i] = 1;
- pos -= dp[i][L];
- break;
- }
- }
- L--;
- }
- UINT i = 1;
- while(res[i] == 0 && 33 - i <= N) i++;
- if(i == N+1) i = 1;
- for(; i <= N; i++)
- fout << res[i];
- fout << endl;
- return 0;
- }
- USACO Stringsobits, 还是得搬出动态规划来
- 【动态规划】【USACO】Stringsobits
- USACO Stringsobits
- usaco Stringsobits
- USACO 3.2.2 stringsobits
- USACO 3.2.2 Stringsobits
- USACO Stringsobits, DP
- USACO 3.2 Stringsobits
- USACO Stringsobits 解题报告
- USACO Section 3.2 Stringsobits
- USACO 3.2 Stringsobits (kimbits)
- USACO 3.2.2:Stringsobits
- USACO--3.1Stringsobits
- usaco 01串 Stringsobits
- usaco 3.2.3 stringsobits
- 【动态规划】【USACO】Stamps
- USACO humble,动态规划简直快得吐血(对比类似treap思路)
- USACO Section 3.2 PROB Stringsobits
- 我的OpenCV学习笔记(13):计算直方图,利用查找表拉伸直方图,直方图均衡
- 点击tomcat出现 unable to open service tomcat
- adb shell dumpsys 命令
- 程序设计就跟我们平时头脑想的是一样的[如何按生日的年月日计算年龄(周岁)]
- 基础服务开发实例
- USACO Stringsobits, 还是得搬出动态规划来
- 笔试面试中C/C++重要知识点整理(不定期更新)
- 将整形转化为二进制存放着数组中
- 素数判定
- 分享我用Qt写的游戏组队群聊系统
- ActionServlet类未找到
- JDBC的支持——DataSource的配置
- 应用Python快速实现系统原型
- 通过反射技术创建窗体实例然后给控件赋值(C#)