2012 ACM/ICPC Asia Regional Changchun Online HDOJ 4272 连连看

   状态压缩dp

因为只有距离5的可以相连,那么,对于每次向下一个数字的时候,最多有10个相邻的数字显示的不同状态。

对于a,最多可能a以下的四个数字已经被a上方的数字相连,所以a最多能连到a以下4 + 5 = 9 个数字,所以对于一个数字最多有10个相连数字的不同状态,

一个数字可能已经被消除(0),可能依然存在(1),所以最多有2^10 - 1  = 1023个状态;

算法依次从顶向底计算,计算到最下面一个数字后看还剩下什么状态,然后看这些状态中是否存在一个状态可以双双连接消除所有数字;

因为最后判断的状态只有10个数字,可以不能考虑距离了,因为可以证明                   5对数字  供10个数怎么放置都可以消除,他们之间是必要关系



题目连接:2012 ACM/ICPC Asia Regional Changchun Online HDOJ 4272



我的代码,很乱啊啊啊啊啊

#include<stdio.h>
#include<string.h>
#define MAX 1001


int array[MAX];
int top;


bool dp[MAX][1025];


int count(int *arr)
{
int num = 0, i;


for(i = 0; i <= 9; i ++)
{
num *= 2;
num += arr[i];

}
return num;
}


int resolve(int x, int *arr)
{
int Top = -1;
for(int i = 9; i >= 0; i --)
{
arr[i] = x % 2;
x /= 2;
if(Top == -1 && arr[i] )
Top = i;
}
return Top;
}
int check()
{
int i, j, num, dis;
int arr[10], k, z;
int Top;
memset(dp, 0, sizeof(dp));
dp[top + 1][0] = 1;
for(i = top; i >= 0; i --)
{


for(j = 0; j < 1024; j ++)
{
if(dp[i + 1][j] == 1)
{
Top = resolve(j, arr);
if(arr[9] == 1)
continue;
for(k = 9; k >= 1; k --)
{
arr[k] = arr[k - 1];
}
arr[0] = 1;
Top ++;

dp[i][count(arr)] = 1;


for(dis = 0, k = Top - 1; k >= 0 && dis < 6; k --)
{
if(arr[k] )
dis ++;
if(array[i + k] == array[i + Top] && arr[k] == 1)
{
num = 0;
for(z = 0; z <= 9; z ++)
{
num *= 2;
if(z != k && z != Top)
num += arr[z];

}
dp[i][num] = 1;
}
}

}
}
}






for(i = 0; i < 1024; i ++)
{
if(dp[0][i] == 1)
{
resolve(i, arr);
for(k = 0; k <= 9; k ++)
{
if(arr[k])
{
for(z = k + 1; z <= 9; z ++)
{
if(arr[z] && array[k] == array[z])
{
arr[k] = 0;
arr[z] = 0;
break;
}
}
}

}
for(k = 0; k <= 9; k ++)
{
if(arr[k] == 1)
{
break;
}
if(k == 9 && arr[k] == 0)
return 1;
}
}
}
return 0;
}


int main()
{
while(scanf("%d", &top) != EOF)
{
for(int i = 0; i < top; i ++)
{
scanf("%d", &array[i]);
}
top --;
if(top % 2 == 1 && check())
printf("1\n");
else
printf("0\n");
}
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值