Integer Transmission UVA

来源:互联网 发布:开博尔网络机顶盒刷机 编辑:程序博客网 时间:2024/06/05 18:56

题目有一定的难度,但是按照紫书的分析思路就会很好做了。首先在于明白一点,出现0与0之间的顺序颠倒以及出现1与1之间的顺序变化其实对最终的结果是没有影响的,那么后续的分析就围绕1与0之间的串扰。代码中首先是将输入的整数进行二进制的表示,然后分别记录0以及1在数组中的位置,其实也就是相应的发射时间。对于0串中特定的某个0以及1串中特定的某个1,我们就要判断是否0可以在1之前发射以及1是否可以在0之前发射,然后就按照贪心算法,要得到最小的值,那么我们就尽量的早发射0,这样越多的0占据高位,那么对应的数字也就越小,同时要得到最大的值,我们就今早地发射1,这样越多的1占据高位,那么所对应的数字也就越大, 上述分为两个过程来进行计算。在上述计算结束之后,就利用紫书上递推的思想,以0和1的发射顺序为基础,进行相应的状态更新即可,具体首先见如下代码:

#include<iostream>#include<vector>#include<string>#include<set>#include<stack>#include<queue>#include<map>#include<algorithm>#include<cmath>#include<iomanip>#include<cstring>#include<sstream>#include<cstdio>#include<deque>using namespace std;const int max_n = 64;typedef long long LL;LL n, d;LL data[max_n];LL One[max_n], Zero[max_n];LL zAmount, oAmount;unsigned long long min_v, max_v;unsigned long long result[max_n][max_n],k;bool getOne(int i,int j){//One,Zeroreturn (i < oAmount) && (j == zAmount || Zero[j] + d >= One[i]);}bool getZero(int i,int j){//One,Zeroreturn (j < zAmount) && (i == oAmount || One[i] + d >= Zero[j]);}void getMaxMin(){int i = 0, j = 0;while (i < oAmount || j < zAmount){if (getZero(i, j)){min_v = min_v * 2;j++;}else{min_v = min_v * 2 + 1;i++;}}i = 0, j = 0;while (i < oAmount || j < zAmount){if (getOne(i, j)){max_v = max_v * 2 + 1;i++;}else{max_v = max_v * 2;j++;}}}void solve(){//i 1,j 0memset(result, 0, sizeof(result));result[0][0] = 1;for (int i = 0; i <= oAmount; i++){for (int j = 0; j <= zAmount; j++){if (getOne(i, j)) result[i + 1][j] += result[i][j];if (getZero(i, j)) result[i][j + 1] += result[i][j];}}cout << result[oAmount][zAmount] << " " << min_v << " " << max_v << endl;}int main(){int kcase = 1;while (cin >> n&&n){cin >> d >> k;min_v = 0;max_v = 0;for (int i = 0; i < n; i++){data[n - 1 - i] = k % 2;k = k / 2;}zAmount = 0;oAmount = 0;for (int i = 0; i < n; i++){if (data[i] == 0){Zero[zAmount++] = i;}else{//data[i]==1One[oAmount++] = i;}}cout << "Case " << kcase++ << ": ";getMaxMin();solve();}return 0;}



原创粉丝点击