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

P4574 [CQOI2013]二进制A+B

时间:2018-09-17 23:00:29      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:mat   fine   inf   ret   cstring   最大值   tar   problem   不同   

传送门

思路:

  本题可用数位DP来做,设 f [ i ][ a ][ b ][ c ][ j ] 表示当前枚举到(二进制下的)第i位,a‘ b‘ c‘各用a,b,c了几个1,j表示最后一位是否有进位。转移方程就只要暴力枚举8种情况(不同位置及是否进位)。

DP方程:

inline void dp()//动态规划,强行枚举八种情况 
{
    f[0][0][0][0][0]=0;
    for (int i=0;i<n;++i)
        for (int j=0;j<=jla;++j)
            for (int k=0;k<=jlb;++k)
                for (int l=0;l<=jlc;++l)
                {
                    long long tmp=f[i][j][k][l][0];//枚举最后一位不进位的情况
                    f[i+1][j+1][k+1][l+1][1]=min(f[i+1][j+1][k+1][l+1][1],tmp+(1<<i+1));
                    f[i+1][j+1][k][l+1][0]=min(f[i+1][j+1][k][l+1][0],tmp+(1<<i));
                    f[i+1][j][k+1][l+1][0]=min(f[i+1][j][k+1][l+1][0],tmp+(1<<i));
                    f[i+1][j][k][l][0]=min(f[i+1][j][k][l][0],tmp);
                    tmp=f[i][j][k][l][1];//枚举最后一位进位的情况
                    f[i+1][j+1][k+1][l+1][1]=min(f[i+1][j+1][k+1][l+1][1],tmp+(1<<i+1));
                    f[i+1][j][k+1][l][1]=min(f[i+1][j][k+1][l][1],tmp+(1<<i));
                    f[i+1][j+1][k][l][1]=min(f[i+1][j+1][k][l][1],tmp+(1<<i));
                    f[i+1][j][k][l][0]=min(f[i+1][j][k][l][0],tmp);
                }
}

完整代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define INF 0x7f7f7f7f7f7f7f
int T,a,b,c;
int n,jla,jlb,jlc;//n记录三个数的二进制数码长度的最大值,jla、jlb、jlc分别记录a、b、c的二进制数码 
long long f[33][33][33][33][2];
inline int read()//快读 
{
    char kr=0;
    char ls;
    for(;ls>9||ls<0;kr=ls,ls=getchar());
    int xs=0;
    for(;ls>=0&&ls<=9;ls=getchar())
    {
        xs=xs*10+ls-48;
    }
    if(kr==-) xs=0-xs;
    return xs;
}
inline int lowbit(int x)//求出x的二进制数码 
{
    int sum=0;
    for (;x;x>>=1)
        sum+=x&1;
    return sum;
}
inline void dp()//动态规划,强行枚举八种情况 
{
    f[0][0][0][0][0]=0;
    for (int i=0;i<n;++i)
        for (int j=0;j<=jla;++j)
            for (int k=0;k<=jlb;++k)
                for (int l=0;l<=jlc;++l)
                {
                    long long tmp=f[i][j][k][l][0];//枚举最后一位不进位的情况
                    f[i+1][j+1][k+1][l+1][1]=min(f[i+1][j+1][k+1][l+1][1],tmp+(1<<i+1));
                    f[i+1][j+1][k][l+1][0]=min(f[i+1][j+1][k][l+1][0],tmp+(1<<i));
                    f[i+1][j][k+1][l+1][0]=min(f[i+1][j][k+1][l+1][0],tmp+(1<<i));
                    f[i+1][j][k][l][0]=min(f[i+1][j][k][l][0],tmp);
                    tmp=f[i][j][k][l][1];//枚举最后一位进位的情况
                    f[i+1][j+1][k+1][l+1][1]=min(f[i+1][j+1][k+1][l+1][1],tmp+(1<<i+1));
                    f[i+1][j][k+1][l][1]=min(f[i+1][j][k+1][l][1],tmp+(1<<i));
                    f[i+1][j+1][k][l][1]=min(f[i+1][j+1][k][l][1],tmp+(1<<i));
                    f[i+1][j][k][l][0]=min(f[i+1][j][k][l][0],tmp);
                }
}
inline void clear()//为做DP初始化 
{
    memset(f,INF,sizeof(f)); 
    n=max((int)log2(a)+1,(int)log2(b)+1);
    n=max(n,(int)log2(c)+1);//求 n 
    jla=lowbit(a),jlb=lowbit(b),jlc=lowbit(c);
}
int main()
{
    a=read();b=read();c=read();
    clear();
    dp();
    if(f[n][jla][jlb][jlc][0]>=INF)//注意是“≥INF” 
    {
        printf("-1\n");
        return 0;
    }//如果无解就输出-1 
    printf("%lld\n",f[n][jla][jlb][jlc][0]);//输出最小值 
    return 0;
}

一些注意事项:

 ①本题的 f 数组要开long long 不然会爆。

 ②INF也要尽量开大。

 ②在判断无解时要判 " ≥ INF ”(因为转移过程中会加上部分的值)   

其他的细节瞎搞搞就AC了。

P4574 [CQOI2013]二进制A+B

标签:mat   fine   inf   ret   cstring   最大值   tar   problem   不同   

原文地址:https://www.cnblogs.com/lck-lck/p/9665321.html

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