您的位置:首页 > 其它

POJ 3373 Changing Digits(DP)

2013-07-07 17:19 344 查看
题目链接

记录路径的DP,看的别人的思路。自己写的也不好,时间居然2000+,中间的取余可以打个表,优化一下。

写的各种错,导致wa很多次,写了一下午,自己构造数据,终于发现了最后一个bug。

dp[i][j]表示前i位取余得到j,需要最少改变多少位。

这样可以得到最少改变多少位了,但是,还要保证,最小。学习别人的题解,开一个标记数组,先从后倒回来,把这些可以达到最小的路径都记录下来。

然后再从头找最小的那一条路径。这样就能保证,最小了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define INF 100000000
int dp[101][10001];
bool o[101][10001];
int que[101];
int main()
{
int i,j,k,n,m,t,z,pos;
char str[101];
while(scanf("%s%d",str,&m)!=EOF)
{
n = strlen(str);
if(n == 1)
{
if((str[0]-'0')%m == 0)
printf("%d\n",str[0]-'0');
else
printf("0\n");
continue;
}
for(i = 0; i < n; i ++)
{
for(j = 0; j < m; j ++)
{
dp[i][j] = INF;
o[i][j] = 0;
}
}
for(i = 1; i < 10; i ++)
{
t = i%m;
if(i == str[0]-'0')
z = 0;
else
z = 1;
dp[0][t] = min(dp[0][t],z);
}
for(i = 0; i < n-1; i ++)
{
for(j = 0; j < m; j ++)
{
if(dp[i][j] == INF) continue;
for(k = 0; k < 10; k ++)
{
if(k == str[i+1]-'0')
z = 0;
else
z = 1;
dp[i+1][(j*10+k)%m] = min(dp[i+1][(j*10+k)%m],dp[i][j]+z);
}
}
}
o[n-1][0] = 1;
for(i = n-2; i >= 0; i --)
{
for(j = 0; j < m; j ++)
{
if(dp[i][j] == INF) continue;
for(k = 0; k < 10; k ++)
{
if(k == str[i+1]-'0')
z = 0;
else
z = 1;
if(dp[i+1][(j*10+k)%m] == dp[i][j]+z&&o[i+1][(j*10+k)%m])
{
o[i][j] = 1;
}
}
}
}
for(i = 1; i < 10; i ++)
{
t = i%m;
if(i == str[0]-'0')
z = 0;
else
z = 1;
if(o[0][t]&&dp[0][t] == z)
{
printf("%d",i);
pos = t;
break;
}
}
for(i = 1;i < n;i ++)
{
for(j = 0;j < 10;j ++)
{
if(j == str[i]-'0')
z = 0;
else
z = 1;
if(o[i][(pos*10+j)%m]&&dp[i][(pos*10+j)%m] == dp[i-1][pos]+z)
{
printf("%d",j);
pos = (pos*10+j)%m;
break;
}
}
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: