POJ 3373 Changing Digits

题目大意:

给出一个数n,求m,使得m的长度和n相等,能被k整除。有多个数符合条件输出与n在每位数字上改变次数最小的。改变次数相同的输出大小最小的。 

共有两种解法:DP解法,记忆化搜索的算法。

以后会更新记忆化搜索。

1、DP解法:

解题思路:

DP[i][j]表示数n的前i位除以k余j最小改变几位。

DP[len][0]就表示数n被k整除最小改变几位。

根据这个关系从后向前遍历DP数组可以找出所有满足条件的数的路径。

再根据关系从前往后输出。 

下面是代码:

#include <stdio.h>
#include <string.h>
int dp[110][10005];
bool vis[110][10005];
int mod;
int min(int a,int b)
{
    if(a>b)a=b;
    return a;
}
int main()
{
    char s[105];
    while(scanf("%s %d",s,&mod)!=EOF)
    {
        memset(dp,0x3f3f,sizeof(dp));
        memset(vis,false,sizeof(vis));
        int len=strlen(s);
        /******特判部分↓*********/
        if(mod==1)
        {
            puts(s);
            continue;
        }
        if(len==1)
        {
            if((s[0]-‘0‘)%mod==0)
            {
                puts(s);
            }
            else printf("%d\n",mod);
            continue;
        }
        /****DP部分  ↓******/
        for(int i=1; i<10; i++)
        {
            if(i==s[0]-‘0‘)
            {
                dp[1][i%mod]=0;
            }
            else
            {
                dp[1][i%mod]=min(dp[1][i%mod],1);
            }
        }
        for(int i=1; i<len; i++)
        {
            for(int j=0; j<mod; j++)
            {
                if(dp[i][j]!=dp[104][0])
                {
                    for(int k=0; k<10; k++)
                    {
                        if(k==s[i]-‘0‘)
                        {
                            if(dp[i+1][(j*10+k)%mod]>dp[i][j])
                            {
                                dp[i+1][(j*10+k)%mod]=dp[i][j];
                            }
                        }
                        else
                        {
                            if(dp[i+1][(j*10+k)%mod]>dp[i][j]+1)
                            {
                                dp[i+1][(j*10+k)%mod]=dp[i][j]+1;
                            }
                        }
                    }
                }
            }
        }
        /*****寻找路径部分    ↓******/
        vis[len][0]=true;
        for(int i=len-1; i>0; i--)
        {
            for(int j=0; j<mod; j++)
            {
                if(dp[i][j]!=dp[104][0])
                {
                    for(int k=0; k<10; k++)
                    {
                        if(vis[i+1][(j*10+k)%mod]&&((dp[i][j]==dp[i+1][(j*10+k)%mod]&&k==s[i]-‘0‘)||(k!=s[i]-‘0‘&&dp[i][j]+1==dp[i+1][(j*10+k)%mod])))
                        {
                            vis[i][j]=true;
                            break;
                        }
                    }
                }
            }
        }
        /*****输出部分   ↓*******/
        int p=1,x=1;
        for(; p<10; p++)
        {
            if(vis[1][p%mod])
            {
                printf("%d",p);
                break;
            }
        }
        while(x<len)
        {
            for(int k=0; k<10; k++)
            {
                if(vis[x+1][(p*10+k)%mod]&&((s[x]-‘0‘==k&&dp[x][p]==dp[x+1][(p*10+k)%mod])||(s[x]-‘0‘!=k&&dp[x][p]+1==dp[x+1][(p*10+k)%mod])))
                {
                    printf("%d",k);
                    p=p*10+k;
                    p%=mod;
                    x++;
                    break;
                }
            }
        }
        puts("");
    }
    return 0;
}

POJ 3373 Changing Digits,布布扣,bubuko.com

时间: 2024-10-12 13:24:32

POJ 3373 Changing Digits的相关文章

POJ 3373 Changing Digits 好蛋疼的DP

一开始写的高位往低位递推,发现这样有些时候保证不了第四条要求.于是又开始写高位往低位的记忆化搜索,又发现传参什么的蛋疼的要死.然后又发现高位开始的记忆化搜索就是从低位往高位的递推呀,遂过之. dp[i][j]记录在i位 且 余数为j时的最优解情况. dp[i][j].next表示当前的最优解是由哪一种状态转移过来的. 代码又写锉了.. #include <algorithm> #include <iostream> #include <cstring> #include

poj 3373

Changing Digits Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 2960   Accepted: 952 Description Given two positive integers n and k, you are asked to generate a new integer, say m, by changing some (maybe none) digits of n, such that th

POJ3373:Changing Digits(记忆化)

Description Given two positive integers n and k, you are asked to generate a new integer, say m, by changing some (maybe none) digits of n, such that the following properties holds: m contains no leading zeros and has the same length as n (We conside

poj 2720 Last Digits

Last Digits Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2233   Accepted: 474 Description Exponentiation of one integer by another often produces very large results. In this problem, we will compute a function based on repeated expone

POJ 搜索题集

poj1010--邮票问题 DFS poj1011--Sticks dfs + 剪枝 poj1020--拼蛋糕 poj1054--The Troublesome Frog poj1062--昂贵的聘礼 poj1077--Eight poj1084--Square Destroyer poj1085--Triangle War(博弈,極大極小搜索+alpha_beta剪枝) poj1088--滑雪 poj1129--Channel Allocation 着色问题 dfs poj1154--lett

POJ题目分类推荐 (很好很有层次感)

著名题单,最初来源不详.直接来源:http://blog.csdn.net/a1dark/article/details/11714009 OJ上的一些水题(可用来练手和增加自信) (POJ 3299,POJ 2159,POJ 2739,POJ 1083,POJ 2262,POJ 1503,POJ 3006,POJ 2255,POJ 3094) 初期: 一.基本算法: 枚举. (POJ 1753,POJ 2965) 贪心(POJ 1328,POJ 2109,POJ 2586) 递归和分治法. 递

poj练习题的方法

poj1010--邮票问题 DFSpoj1011--Sticks dfs + 剪枝poj1020--拼蛋糕poj1054--The Troublesome Frogpoj1062--昂贵的聘礼poj1077--Eightpoj1084--Square Destroyerpoj1085--Triangle War(博弈,極大極小搜索+alpha_beta剪枝)poj1088--滑雪poj1129--Channel Allocation 着色问题 dfspoj1154--letters (dfs)p

POJ 刷题指南

OJ上的一些水题(可用来练手和增加自信) (POJ 3299,POJ 2159,POJ 2739,POJ 1083,POJ 2262,POJ 1503,POJ 3006,POJ 2255,POJ 3094) 初期: 一.基本算法: 枚举. (POJ 1753,POJ 2965) 贪心(POJ 1328,POJ 2109,POJ 2586) 递归和分治法. 递推. 构造法.(POJ 3295) 模拟法.(POJ 1068,POJ 2632,POJ 1573,POJ 2993,POJ 2996) 二

sed2

<!doctype html>Markdoc Preview html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary { display: block } audio,canvas,progress,video { display: inline-block; vertical