POJ 3373 Changing Digits(記錄路徑的dp)

畫船聽雨發表於2014-05-29

很長時間之前看的一道題目,一直以為是搜尋。結果發現是dp,輸出路徑即可。

題目大意:給你一個n,k。找一個m使得m的長度與n一樣,而且m要儘量多的元素保持和n一樣。一樣的條件下要選擇一個最小的輸出。(從小到大列舉就可以滿足找到的最小)

dp[i][j] 表示i位置是的餘數為j此時有多少位數字是不同的。

pre[i][j][k]k = 1表示第i位餘數為j時取得數字是多少,k = 0 表示第i位餘數為j時的前一個狀態的餘數是多少。(記錄前驅)。

注意預處理出來大數的餘數,這很重要。

Changing Digits
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 2910   Accepted: 933

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:

  1. m contains no leading zeros and has the same length as n (We consider zero itself a one-digit integer without leading zeros.)
  2. m is divisible by k
  3. among all numbers satisfying properties 1 and 2, m would be the one with least number of digits different from n
  4. among all numbers satisfying properties 1, 2 and 3, m would be the smallest one

Input

There are multiple test cases for the input. Each test case consists of two lines, which contains n(1≤n≤10100) and k(1≤k≤104kn) for each line. Both n and k will not contain leading zeros.

Output

Output one line for each test case containing the desired number m.

Sample Input

2
2
619103
3219

Sample Output

2
119103
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-7
#define M 1000100
///#define LL __int64
#define LL long long
#define INF 0x3fffffff
#define PI 3.1415926535898

using namespace std;

const int maxn = 110;

int dp[maxn][maxn*maxn];
int pre[maxn][maxn*maxn][2];
int mod[maxn][10];
char str[maxn];
int k;
int len;

void dfs(int x, int y)
{
    if(x > len)
        return;
    cout<<pre[x][y][1];
    dfs(x+1, pre[x][y][0]);
}
int main()
{
    while(cin >>(str+1)>>k)
    {
        len = strlen(str+1);
        for(int i = 0; i <= 9; i++)
            mod[len][i] = i%k;
        for(int i = len-1; i >= 1; i--)
            for(int j = 0; j <= 9; j++)
                mod[i][j] = (mod[i+1][j]*10)%k;
        memset(dp, -1, sizeof(dp));
        dp[len+1][0] = 0;
        for(int i = len; i >= 1; i--)
        {
            int p = 0;
            if(i == 1)
                p = 1;
            for(; p <= 9; p++)
            {
                for(int j = 0; j < k; j++)
                {
                    if(dp[i+1][j] != -1)
                    {

                        int ff = 1;
                        if((str[i]-'0') == p)
                            ff = 0;
                        int kk = (mod[i][p]+j)%k;
                        if(dp[i][kk] == -1 || (dp[i+1][j]+ff < dp[i][kk]))
                        {
                            dp[i][kk] = dp[i+1][j]+ff;
                            pre[i][kk][1] = p;
                            pre[i][kk][0] = j;
                        }
                    }
                }
            }
        }
        dfs(1, 0);
        cout<<endl;
    }
    return 0;
}


相關文章