您的位置:首页 > 其它

HDU 4433 locker 2012 Asia Tianjin Regional Contest 状态压缩DP

2014-10-16 15:37 148 查看
题意:给出一个长度最长为1000的数字序列,像密码锁一样,你可以上下滑动,同时会0-9的循环。每次操作,最多对连续的三个数字操作。现在给出起始序列和目标序列,求出最少的操作次数,从起始序列到目标序列。

想这道题花了一天的时间,我认为是道很难的DP。这个阶段很好划分,对于前面完成的密码锁就不再考虑。问题的关键是这个旋转每次可以的情况很多。

同时也可以发现当I位置上确定移好后,至多影响到后两位,-> dp[i][j][k] 表示当前i位移好后,i+1 为j , i+2为k 的次数。

这里同时使用一个预处理技巧,对于一个移动操作,有向上向下两种。当将一个值转到另一个值,up[i][j]=(j-i+10)%10;down[i][j]=(i-j+10)%10; i->j 的方法

在dp中必然会有对于阶段的描述,一般从1开始,表达每一段。这里为了求dp
[0][0] 在最后再补上两位。

dp[0][s[0]][s[1]]=0;
刚开始0阶段,一个都未完成的时候,即前0次移好i+1,i+2位为这样的次数为0

int r=up[j][t[i-1]];//①
dp[i][(k+u)%10][(s[i+1]+v)%10]=min(...)//②



这两句话是我刚开始一直困惑的地方。首先要明确转移方程是阶段间的转移dp[i-1][...][...]->dp[i][...][...]

这样看,配合②我们发现当dp[i-1][j][k]已知,dp[i][...][...]是将其 j转为t[i-1]。(这个是理解的关键)。这里的u,v表明的是在j转为t[i-1]过程中,后两位的改变情况枚举值。

dp[i][(k+u)%10][(s[i+1]+v)%10] 这个现在就可以理解了,对于dp[i-1]的j 现在dp[i]考虑的就是上次的K了。

还有一点就是标号很乱一会是阶段的i,一会又是起始位置.......

#include <stdio.h>
#include <string.h>
#include <map>
#include <iostream>
#define inf 0x3fffffff
const int maxn=1010;
typedef unsigned __int64 ull;
using namespace std;
char s[maxn],t[maxn];
int dp[maxn][10][10];
int up[10][10],down[10][10];
int min(int a,int b)
{
return a<b?a:b;
}
void init()
{
int i,j;
for(i=0;i<10;i++)
for(j=0;j<10;j++)
{
up[i][j]=(j-i+10)%10;
down[i][j]=(i-j+10)%10;
}
}

int main()
{
init();
while(~scanf("%s%s",s,t))
{
memset(dp,0x3f,sizeof(dp));
int i,j,k,u,v;
int n=strlen(s);
s
=s[n+1]=t
=t[n+1]=0;
for(i=0;i<n;i++)
s[i]-='0',t[i]-='0';
dp[0][s[0]][s[1]]=0;//除了最初的序列,其他的dp都没有合法值
for(i=1;i<=n;i++)
{
for(j=0;j<10;j++)//枚举两位数字的每一位
{
for(k=0;k<10;k++)
{
int r=up[j][t[i-1]];//从j转到t[i-1]的次数,将三位中最左边的数字向上转到目标序列需要的操作
for(u=0;u<=r;u++)//枚举可能出现的操作
{
for(v=0;v<=u;v++)
dp[i][(k+u)%10][(s[i+1]+v)%10]=min(dp[i][(k + u) % 10][(s[i+1] + v) % 10], dp[i-1][j][k] + r);
}
r=down[j][t[i-1]];
for(u=0;u<=r;u++)
for(v=0;v<=u;v++)
dp[i][(k-u+10)%10][(s[i+1]-v+10)%10]=min(dp[i][(k - u+10) % 10][(s[i+1] - v +10) % 10], dp[i-1][j][k] + r);
}
}
}
printf("%d\n",dp
[0][0]);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: