/**//* 可改变数字串A的每一位,串A的长度n<=100 求改变出的新串(不能有前缀0),需要是x<=10^4的倍数 满足改变的次数最少,再满足数字最小
自己想出的-.- 通过构造出“新串/x的商S”来得到新串,S可从右到左逐位枚举 如A = 176, x = 13 <--12 13------ 156
状态为dp[pos, pre]表示在第pos位(0<=pos<n),且以后算pos+1时, 实际数字需要加上pre时,[pos,n)已改变好的最小改变位数 转移是枚举第pos-1位的商会是多少j,变为 dp[pos-1][(pre+x*j)/10] = dp[pos][pre] + ((pre+x*j) % 10 + '0' != A[i-1])
对于不为前置0的情况,就是算到pos=1,枚举dp[1,j](就是说第0位是j了)
网上貌似很多都是搜索的? */ #include<iostream> #include<cstring> #include<map> #include<algorithm> #include<stack> #include<queue> #include<cstring> #include<cmath> #include<string> #include<cstdlib> #include<vector> #include<cstdio> #include<set> #include<list> #include<numeric> #include<cassert> #include<sstream> #include<ctime> #include<bitset> #include<functional>
using namespace std;
const int INF = 0x3f3f3f3f;
char dp[102][10086], way[102][10086]; char A[110], ans[110][10086]; int nine[] = {9, 99, 999, 9999, 99999}; int n, m, x;
void print(int pos, int pre) { if (pos == n) { puts(""); return; } putchar(ans[pos][pre]); print(pos+1, pre*10 + (ans[pos][pre] - '0') - x*way[pos][pre]); }
int main() { #ifndef ONLINE_JUDGE freopen("in","r",stdin); #endif
for (;~scanf("%s%d", A, &x);) { n = strlen(A); for (int i = 0; i < n; i++) { fill(dp[i], dp[i]+x, 120); } for (int j = 0; j < 10; j++) { char ch = x*j%10 + '0'; if (dp[n-1][x*j/10] > (ch != A[n-1]) ) { dp[n-1][x*j/10] = (ch != A[n-1]); way[n-1][x*j/10] = j; ans[n-1][x*j/10] = ch; } } for (int i = n-1; i > 1; i-- ) { for (int pre = 0; pre < x && (i > 4 || pre <= nine[i]); pre++) { if (dp[i][pre] == 120) { continue; } //从右往左枚举就少了一个枚举第i位的 for (int j = 0; j < 10; j++){ int _pre = (pre+x*j)/10; char ch = (pre+x*j)%10 + '0'; int tmp = dp[i][pre] + (ch != A[i-1]); if (dp[i-1][_pre] > tmp) { dp[i-1][_pre] = tmp; way[i-1][_pre] = j; ans[i-1][_pre] = ch; } } } } if ( n > 1 ){ int J = -1, Min = 120; for (int j = 1; j < 10; j++) { if (dp[1][j] + (j+'0' != A[0]) < Min) { Min = dp[1][j] + (j+'0' != A[0]); J = j; } } putchar(J+'0'); print(1, J); } else { print(0,0); } } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|