UVA - 1228 Integer Transmission 整数传输 递推

来源:互联网 发布:ipad专业绘画软件 编辑:程序博客网 时间:2024/05/29 03:57

题目



约制1:同是1或者同是0的数字其相对位置不变。


       求最大最小可用贪心求解。

    

简化题目:若延迟为d,从左往右数第i个数字到达的时间范围可以记为[i,i+d],题目说是[i+1,i+d+1],不影响结果。


约制2(书上说的,实际解题我的代码没有用到,但这是对的):假若有n位数字,到达的时间是[1,n+d],我们可以修改为[1,n]不影响结果。


化为dp中的一个常见模型,两个序列,一次从左往右取dp[i][j]代表第一个序列去了i个,第二个序列取了j个时的最优解。


然而这个题目不是最优解,严格地说这个题目是递推,而不是动归。


/**========================================== *   This is a solution for ACM/ICPC problem * *   @source:uva 1228 Integer Transmission *   @type:  dp *   @author: wust_ysk *   @blog:  http://blog.csdn.net/yskyskyer123 *   @email: 2530094312@qq.com *===========================================*/#define REP(i,n)  for(int i=0 ;i<(n) ;i++)#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<vector>using namespace std;typedef long long ll;const int INF =0x3f3f3f3f;const int maxn= 64   ;int n,d,numZero,numOne;unsigned long long k;int kase=0;vector<int >ve1;vector<int >ve0;struct A{    int x;    int ind;}a[maxn+3] ;unsigned long long dp[maxn+3][maxn+3];bool cmp1(A x,A y){    if(x.x==y.x)  return   x.ind<y.ind;    else if(x.x==0)  return x.ind<=y.ind+d;    return   x.ind+d<y.ind;}bool cmp2(A x,A y){    if(x.x==y.x)  return   x.ind<y.ind;    else if(x.x==0)  return x.ind+d<y.ind;    return   x.ind<=y.ind+d;}void getA(){    ve0.clear();    ve1.clear();    numZero=numOne=0;    unsigned long long t=k;    for(int i=n-1;i>=0;i--)    {        a[i].x=t%2;        a[i].ind=i;        t/=2;    }    REP(i,n)    {        if(a[i].x)  numOne++, ve1.push_back(i);        else   numZero++, ve0.push_back(i);    }}void getmin(){    sort(a,a+n,cmp1);    unsigned long long x=0;    REP(i,n)    {        x=2*x+a[i].x;    }    printf(" %llu",x);}void getmax(){    sort(a,a+n,cmp2);    unsigned long long x=0;    REP(i,n)    {        x=2*x+a[i].x;    }    printf(" %llu\n",x);}bool can(int numz,int numo ,int now){    if(now==0)    {        if(numz==numZero)  return false;        if(numo==numOne)  return true;        return ve0[numz]<=ve1[numo]+d  ;    }    if(now==1)    {        if(numo==numOne)  return false;        if(numz==numZero)  return true;        return ve1[numo]<=ve0[numz]+d  ;    }}void work(){   dp[0][0]=1;   for(int i=0;i<=numZero;i++)   {       for(int j=0;j<=numOne;j++)       {           if(!i&&!j)  {dp[i][j]=1;continue;}           dp[i][j]=0;           if (i-1>=0&&can(i-1,j,0) )  dp[i][j]+=dp[i-1][j];           if (j-1>=0&&can(i,j-1,1) )  dp[i][j]+=dp[i][j-1];       }   }   printf(" %llu",dp[numZero][numOne]);}int main(){    while(~scanf("%d",&n)&&n)    {        scanf("%d%llu",&d,&k);        printf("Case %d:",++kase);        getA();        work();        getmin();        getmax();    }   return 0;}






0 0