[CF792C] Divide by Three(dp,记录路径)
题目链接:http://codeforces.com/contest/792/problem/C
题意:给个超长整数,问最少删掉几个数,使得这个数能被3整除。输出这个删掉字符后的字符串。
当然这个数各位加起来能被三整除,那么这个数就能被三整除。
很容易的dp,f(i,j)表示前i个字符各位和%3=j时,最少删掉几个字符。每层初始化为f(i,j) = min(f(i,j), f(i-1,j)+1)
转移就很简单,当前数为x,那么当前可以由f(i-1,(j-x+3)%3)转移过来。
有几个坑需要注意下:
1.初始化,要特别小心前导零存在的时候(s[0]-'0')%3==0的情况,因此判断一下是更新两个初始值还是一个就行。
2.再就是前导零处理起来特别麻烦,太麻烦了,参考了mengxiang巨的前导零排除方法,用每层初始化的值(删除)和当前字符个数判断,假如全删了,那说明当前状态之前都是0,后面就不转移了。
3.假如删了n个字符,要处理一下这个字符串是不是原本就有0,因为排除前导零的时候没有转移。
1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <bits/stdc++.h> 18 using namespace std; 19 #define fr first 20 #define sc second 21 #define cl clear 22 #define BUG puts("here!!!") 23 #define W(a) while(a--) 24 #define pb(a) push_back(a) 25 #define Rint(a) scanf("%d", &a) 26 #define Rll(a) scanf("%I64d", &a) 27 #define Rs(a) scanf("%s", a) 28 #define Cin(a) cin >> a 29 #define FRead() freopen("in", "r", stdin) 30 #define FWrite() freopen("out", "w", stdout) 31 #define Rep(i, len) for(int i = 0; i < (len); i++) 32 #define For(i, a, len) for(int i = (a); i < (len); i++) 33 #define Cls(a) memset((a), 0, sizeof(a)) 34 #define Clr(a, x) memset((a), (x), sizeof(a)) 35 #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) 36 #define lrt rt << 1 37 #define rrt rt << 1 | 1 38 #define pi 3.14159265359 39 #define RT return 40 #define lowbit(x) x & (-x) 41 #define onenum(x) __builtin_popcount(x) 42 typedef long long LL; 43 typedef long double LD; 44 typedef unsigned long long ULL; 45 typedef pair<int, int> pii; 46 typedef pair<string, int> psi; 47 typedef pair<LL, LL> pll; 48 typedef map<string, int> msi; 49 typedef vector<int> vi; 50 typedef vector<LL> vl; 51 typedef vector<vl> vvl; 52 typedef vector<bool> vb; 53 54 const int maxn = 101010; 55 const int inf = 0x7f7f7f7f; 56 int n, f[maxn][3], path[maxn][3]; 57 char s[maxn]; 58 59 signed main() { 60 // FRead(); 61 while(~Rs(s)) { 62 n = strlen(s); 63 if(n == 1) { 64 if((s[0]-'0')%3==0) puts(s); 65 else puts("-1"); 66 continue; 67 } 68 Clr(f, 0x7f); Clr(path, -1); 69 if((s[0]-'0')%3==0) f[0][0] = 0; 70 else f[0][0] = 1, f[0][(s[0]-'0')%3] = 0; 71 For(i, 1, n) { 72 int x = (s[i] - '0') % 3; 73 Rep(j, 3) { // delete 74 if(f[i][j] > f[i-1][j] + 1) { 75 f[i][j] = f[i-1][j] + 1; 76 path[i][j] = j; 77 } 78 } 79 Rep(j, 3) { 80 if(x == 0) { 81 if(s[i] == '0') { 82 if(f[i-1][j] == i) { 83 continue; // 0 84 } 85 } 86 } 87 int pre = (j - x + 3) % 3; 88 if(f[i][j] > f[i-1][pre]) { 89 f[i][j] = f[i-1][pre]; 90 path[i][j] = pre; 91 } 92 } 93 } 94 // cout << f[n-1][0] << endl; 95 if(f[n-1][0] == n) { 96 bool ok = 0; 97 Rep(i, n) if(s[i] == '0') ok = 1; 98 if(ok) puts("0"); 99 else puts("-1"); 100 continue; 101 } 102 int i = n - 1, j = 0, pre; 103 string ret = ""; 104 while(i) { 105 pre = path[i][j]; 106 if(f[i-1][pre] == f[i][j]) ret += s[i]; 107 j = pre; i--; 108 } 109 if((s[i] - '0') % 3 == pre) ret += s[i]; 110 reverse(ret.begin(), ret.end()); 111 cout << ret << endl; 112 } 113 RT 0; 114 }