dp-史上最戳最长最臭代码-hdu-4733-G(x)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4733

题目大意:

定义G(x)=x(x>>1).给两个由0、1、?组成的长度相同的字符串S1,S2.其中?表示0、1状态不确定,求有多少种p,使得G(p)=S1,G(p+1)=S2

如果p唯一,则输出G(p)和G(p+1)(注意这中间不能有问号)。

解题思路:

这是我写的史上最臭最长最戳的代码,大神请跳过。

 分析函数G(x)=x⊕(x>>1) 也就是右移一位再抑或,从高位出发,构造p和p+1串,先分别放一个0到p和p+1(右移高位时补零的),然后根据S1和S2的状态以及p和p+1的前一状态构造出当前的p和p+1状态,

构造方法:

若S='0'则当前的p和前一位p相同,否则相反(0《-》1)

 如果S='?',则可以尝试00 01 10 11四种状态。

再来分析p和p+1的特点。

 1、最低位肯定不一样。

 2、除最后一位外,前面每一位要么相同,要么p

综合G(x)和p与p+1的特点,可以构造dp状态,

dp[i][j][0][len]:表示当p的第len位为i,p+1的第len位为j,且p

dp[i][j][1][len]:表示当p的第len位为i,p+1的第len位为j,且p=q时的总数。

根据当前的S和前面一位的状态可以递推出当前的位的P和p+1。

注意:

1、最后一位要单独处理。(01或10)

2、只有一种的情况时要记录路径 ,把S中的?确定下来。

比如?    ?   答案为0,1而不是?,? 

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-6
#define INF 0x3fffffff
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 110000
#define M 1000000007

//分别记录达到该状态时的上一状态的第一串和第二串的值,以及是否相等的状态
int path1[2][2][2][Maxn],path2[2][2][2][Maxn],path3[2][2][2][Maxn];
int dp[2][2][2][Maxn];
char sa1[Maxn],sa2[Maxn];
char ans1[Maxn],ans2[Maxn];

int main()
{
    int tt;

    scanf("%d",&tt);
    for(int ca=1;ca<=tt;ca++)
    {
        scanf("%s%s",sa1+1,sa2+1);
        int len=strlen(sa1+1);
        memset(dp,-1,sizeof(dp));
        path2[0][0][1][0]=path1[0][0][1][0]=-1;
        path3[0][0][1][0]=-1;

        int la1=0,la2=0;
        dp[0][0][1][0]=1; //第三维1表示相等 0表示小于
        for(int i=1;i<=len;i++)
        {
            if(sa1[i]!='?'&&sa2[i]!='?')
            {
                for(int la1=0;la1<=1;la1++)
                    for(int la2=0;la2<=1;la2++)
                    {
                        int p,q;
                        p=(sa1[i]=='0')?(la1):(la1^1); //构造出当前状态
                        q=(sa2[i]=='0')?(la2):(la2^1);

                        for(int t=0;t<=1;t++)
                        {
                            if(dp[la1][la2][t][i-1]==-1)//前面状态无效
                                continue;
                            if(i==len) //最后一位单独处理
                            {
                                if(p==q) //最后一位只能是0、1或者1,0
                                    continue;
                                if(p) //P串中为1时,P+1串肯定为0
                                {
                                    if(!t) //并且前面Pq) //这种情况不存在
                                    continue;
                                if(dp[la1][la2][t][i-1]==-1)
                                    continue;
                                if(p=1)
            {
                int aa=path1[a][b][tmp][i+1];
                int bb=path2[a][b][tmp][i+1];
                int tmm=path3[a][b][tmp][i+1];
                sa1[i]=aa+'0';
                sa2[i]=bb+'0';
                a=aa,b=bb,tmp=tmm;
                i--;
            } //先求出P 和 P+1 然后求出G(p)和G(p+1)
           // printf("%s\n%s\n",sa1+1,sa2+1);
            sa1[0]=sa2[0]='0';
            for(int i=1;i<=len;i++)
            {
               ans1[i]=(sa1[i]==sa1[i-1])?'0':'1';
               ans2[i]=(sa2[i]==sa2[i-1])?'0':'1';

            }
            ans1[len+1]=ans2[len+1]='\0';
            printf("%s\n%s\n",ans1+1,ans2+1);

        }
        else if(ans==0)
            printf("Impossible\n");
        else
            printf("Ambiguous %d\n",ans);
    }
   return 0;
}



你可能感兴趣的:(动态规划)