zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    passwd: Have exhausted maximum number of retries for service
    将单个文件上传到多机器工具
    leetcode-Jump game II
    LeetCode--Combination Sum --ZZ
    Leetcode- Find Minimum in Rotated Sorted Array-ZZ
    leetcode-permutation sequence
    leetcode-next permutation
    LeetCode-Subsets ZZ
    leetcode-Restore IP Addresses-ZZ
    leetcode-palindrome partitioning-ZZ
  • 原文地址:https://www.cnblogs.com/kirai/p/7388853.html
Copyright © 2011-2022 走看看