传送门:https://codeforces.com/problemset/problem/792/C

题意:给你一个字符串,要求让你删除最少个数的元素,使得最终答案是没有前导0并且是3的倍数。

题解:模拟:既然是3的倍数,那么第一步肯定是将每个都模上3,讨论长度为1的特殊情况,然后,我们讨论数字模上 3后的和sum

    如果sum为0 直接输出,

    如果sum为1,我们就要删去一个mod3为1的数或者两个mod3为2的数      

    如果sum为2,我们就要删去一个mod3为2的数或者两个mod3为1的数

代码如下:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. char s[];
  4. int a[];
  5. int t,flag,n,p;
  6. int main(){
  7. scanf("%s",s+);
  8. n=strlen(s+);
  9. for(int i=;i<=n;i++){
  10. t=(t+s[i])%;
  11. a[s[i]%]++;
  12. }
  13. //相加和为0直接输出
  14. if(!t){
  15. puts(s+);
  16. return ;
  17. }
  18. for(p=;s[p]=='';p++);
  19. p-=;
  20.  
  21. if(a[t]&&n>&&(p<=||a[t]>||s[]%!=t))
  22. a[t]--;
  23. else if(a[-t]>&&n>)
  24. a[-t]-=;
  25. else if(a[t]&&n>)
  26. a[t]--;
  27. else {
  28. puts("-1");
  29. return ;
  30. }
  31. /*
  32.   t==1,那么我们可以删去一个模3等于1的数字位,
  33. 或者删去两个模3等于2的数字位(这个很容易漏)。
  34. */
  35. /*
  36.   t==2,可以删去一个模3等于2的数字位,
  37. 或者删去两个模3等于1的数字位。
  38. */
  39. for(int i=;i<=n;i++){
  40. if(s[i]==''&&!flag) continue;
  41. if(a[s[i]%]) {
  42. putchar(s[i]);
  43. a[s[i]%]--;
  44. flag=;
  45. }
  46. }
  47. if(!flag) puts("");
  48. }

   动态规划:

    设定dp[i][3]=x表示:

  1.dp[i][0]:[0~i]中剩余的数字每个位子相加模3为0的删除最少元素的个数。

  2.dp[i][1]:[0~i]中剩余的数字每个位子相加模3为1的删除最少元素的个数。

  3.dp[i][2]:[0~i]中剩余的数字每个位子相加模3为2的删除最少元素的个数。

  dp[i][j]=min(dp[i][j],dp[i-1][((j-a[i]%3)%3+3)%3)];

代码如下:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int mod = ;
  4. const int maxn = 1e5+;
  5. const int INF = 0x3f3f3f3f;
  6. int dp[maxn][];
  7. int pre[maxn][];
  8. char str[maxn];
  9. char ans[maxn];
  10. int main(){
  11. while(cin>>str){
  12. int n=strlen(str);
  13. if(n==){
  14. if((str[]-'')%==) printf("%c\n",str[]);
  15. else printf("-1\n");
  16. continue;
  17. }
  18. memset(pre,-,sizeof(pre));
  19. memset(dp,INF,sizeof(dp));
  20. dp[][]=;
  21. dp[][(str[]-'')%]=;
  22. for(int i=;i<n;i++){
  23. for(int j=;j<;j++){
  24. if(dp[i-][j]+<dp[i][j]){
  25. dp[i][j]=dp[i-][j]+;
  26. pre[i][j]=j;
  27. }
  28. if((str[i]-'')%==){
  29. if(str[i]==''){
  30. if(dp[i-][j]!=i&&dp[i-][j]<dp[i][j]){
  31. dp[i][j]=dp[i-][j];
  32. pre[i][j]=j;
  33. }
  34. }else{
  35. if(dp[i-][j]<dp[i][j]){
  36. dp[i][j]=dp[i-][j];
  37. pre[i][j]=j;
  38. }
  39. }
  40. }
  41. if((str[i]-'')%==&&dp[i-][((j-)%mod+mod)%mod]<dp[i][j]){
  42. dp[i][j]=dp[i-][((j-)%mod+mod)%mod];
  43. pre[i][j]=((j-)%mod+mod)%mod;
  44. }
  45. if((str[i]-'')%==&&dp[i-][((j-)%mod+mod)%mod]<dp[i][j]){
  46. dp[i][j]=dp[i-][((j-)%mod+mod)%mod];
  47. pre[i][j]=((j-)%mod+mod)%mod;
  48. }
  49. }
  50. }
  51. if(dp[n-][]==n){
  52. int flag=;
  53. for(int i=;i<n;i++){
  54. if(str[i]=='') flag=;
  55. }
  56. if(flag==) printf("0\n");
  57. else printf("-1\n");
  58. continue;
  59. }
  60. int cnt=;
  61. int now=n-;
  62. int j=;
  63. while(now>=){
  64. int pree=pre[now][j];
  65. if(dp[now-][pree]==dp[now][j]){
  66. ans[cnt++]=str[now];
  67. }
  68. j=pree;
  69. now--;
  70. if(now==){
  71. if(pree==(str[]-'')%){
  72. ans[cnt++]=str[now];
  73. }
  74. }
  75. }
  76. for(int i=cnt-;i>=;i--){
  77. printf("%c",ans[i]);
  78. }
  79. printf("\n");
  80. }
  81. }

codeforces 792CDivide by Three(两种方法:模拟、动态规划的更多相关文章

  1. 探讨instanceof实现原理,并用两种方法模拟实现 instanceof

    在开始之前先了解下js数据类型 js基本数据类型: null undefined number boolean string js引用数据类型: function object array 一说ins ...

  2. Loadrunner 接口测试的两种方法

    其实无论用那种测试方法,接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文,服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端,客户端接收应答报文这一个过程. 方法一.用Lo ...

  3. 安卓ListView操作的两种方法

    举例做一个微信的中间部分(好友消息等信息通知) 第一种:BaseAdapter() package com.example.wx; import java.util.ArrayList;import ...

  4. 在Activity中响应ListView内部按钮的点击事件的两种方法!!!

    在Activity中响应ListView内部按钮的点击事件的两种方法 转载:http://www.cnblogs.com/ivan-xu/p/4124967.html 最近交流群里面有人问到一个问题: ...

  5. 计算理论:NFA转DFA的两种方法

    本文将以两种方法实现NFA转DFA,并利用C语言实现. 方法二已利用HNU OJ系统验证,方法一迷之WA,但思路应该是对的,自试方案,测试均通过. (主要是思路,AC均浮云,大概又有什么奇怪的Case ...

  6. SQL Server中灾难时备份结尾日志(Tail of log)的两种方法

    转自:http://www.cnblogs.com/CareySon/archive/2012/02/23/2365006.html SQL Server中灾难时备份结尾日志(Tail of log) ...

  7. Java 创建线程的两种方法

    Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线 ...

  8. 【java基础 13】两种方法判断hashmap中是否形成环形链表

    导读:额,我介绍的这两种方法,有点蠢啊,小打小闹的那种,后来我查了查资料,别人都起了好高大上的名字,不过,本篇博客,我还是用何下下的风格来写.两种方法,一种是丢手绢法,另外一种,是迷路法. 这两种方法 ...

  9. windows下获取IP地址的两种方法

    windows下获取IP地址的两种方法: 一种可以获取IPv4和IPv6,但是需要WSAStartup: 一种只能取到IPv4,但是不需要WSAStartup: 如下: 方法一:(可以获取IPv4和I ...

  10. android 之 启动画面的两种方法

    现在,当我们打开任意的一个app时,其中的大部分都会显示一个启动界面,展示本公司的logo和当前的版本,有的则直接把广告放到了上面.启动画面的可以分为两种设置方式:一种是两个Activity实现,和一 ...

随机推荐

  1. 网站漏洞修复之最新版本UEditor漏洞

    UEditor于近日被曝出高危漏洞,包括目前官方UEditor 1.4.3.3 最新版本,都受到此漏洞的影响,ueditor是百度官方技术团队开发的一套前端编辑器,可以上传图片,写文字,支持自定义的h ...

  2. 毕业2年 Summary

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/135 看了下去年写毕业一周年总结的时间:2017-6-16,今天 ...

  3. HyperLedger Fabric 1.4 区块链开发平台(4.1)

    目前区块链开发平台分“公有链平台”和“联盟链系统”两类,“公有链平台”主要以以太坊为主的平台,可以在该类平台上进行代币的发行和根据各种模块搭建应用:“联盟链系统”主要以超级账本为主的开源系统,该类开源 ...

  4. (数据科学学习手札35)tensorflow初体验

    一.简介 TensorFlow时谷歌于2015年11月宣布在Github上开源的第二代分布式机器学习系统,目前仍处于快速开发迭代中,有大量的新功能新特性在陆续研发中: TensorFlow既是一个实现 ...

  5. R语言绘图:时间序列分析 ggplot2绘制ACF PACF

    R语言真是博大精深 方法一 Acf(gold[,2], type = "correlation",lag.max = 100) Acf(gold[,2], type = " ...

  6. 开学测试之——ATM

    ---恢复内容开始--- package ATM;   //信1705-2 20173568 李泽宇   import java.util.*; import java.io.File; import ...

  7. python保留关键字和常用关键字

    python保留关键字和常用关键字如下: 上图是python3中的关键字,python2.7中的关键字部分会有区别,具体在自己打印输出查看: import keyword print ' '.join ...

  8. jenkins手动安装插件

    插件下载地址: 搜索:https://plugins.jenkins.io/ 列表:https://updates.jenkins-ci.org/download/plugins/ 打开jenkins ...

  9. Ubuntu下使用Git_4

    在这个第四个文章中,我将练习GIT的高级阶段了,由于高级阶段的内容转的比较多,我自己的代码除了我自己可以看懂意外,大家可能看不懂,所以我将会按照 http://git.wiki.navisec.it/ ...

  10. CCF-NOIP-2018 提高组(复赛) 模拟试题(七)

    T1 Adjoin [问题描述] 定义一种合法的\(0-1\)串:串中任何一个数字都与\(1\)相邻.例如长度为$ 3 的 0-1 $串中,\(101\)是非法的,因为两边的\(1\)没有相邻的\(1 ...