CodeForces 404D Minesweeper 1D (DP)

题意:给定一个序列,*表示雷,1表示它旁边有一个雷,2表示它旁边有两个雷,0表示旁边没有雷,?表示未知,求有多少情况。

析:dp[i][j] 表示第 i 个放 j 状态,有多少种情况,然后很简单的DP就可以搞定。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e16;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1000000 + 10;
const int mod = 1000000007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
  return r >= 0 && r < n && c >= 0 && c < m;
}
LL dp[2][5];
char s[maxn];
/*
0 - 0
1 - *1
2 - 1*
3 - *2*
4 - *
*/

int main(){
  cin >> s+1;
  n = strlen(s+1);
  int cnt = 0;
  if(s[1] == ‘0‘)  dp[cnt][0] = 1;
  else if(s[1] == ‘1‘)  dp[cnt][2] = 1;
  else if(s[1] == ‘*‘)  dp[cnt][4] = 1;
  else if(s[1] == ‘?‘)  dp[cnt][0] = dp[cnt][2] = dp[cnt][4] = 1;
  cnt ^= 1;

  for(int i = 2; i <= n; ++i, cnt ^= 1){
    memset(dp[cnt], 0, sizeof dp[cnt]);
    if(s[i] == ‘0‘)
      dp[cnt][0] = (dp[cnt^1][0] + dp[cnt^1][1]) % mod;
    else if(s[i] == ‘1‘){
      dp[cnt][1] = dp[cnt^1][4];
      dp[cnt][2] = (dp[cnt^1][0] + dp[cnt^1][1]) % mod;
    }
    else if(s[i] == ‘2‘)
      dp[cnt][3] = dp[cnt^1][4];
    else if(s[i] == ‘*‘)
      dp[cnt][4] = (dp[cnt^1][2] + dp[cnt^1][3] + dp[cnt^1][4]) % mod;
    else {
      dp[cnt][0] = (dp[cnt^1][0] + dp[cnt^1][1]) % mod;
      dp[cnt][1] = dp[cnt^1][4];
      dp[cnt][2] = (dp[cnt^1][0] + dp[cnt^1][1]) % mod;
      dp[cnt][3] = dp[cnt^1][4];
      dp[cnt][4] = (dp[cnt^1][2] + dp[cnt^1][3] + dp[cnt^1][4]) % mod;
    }
  }

  LL ans = dp[cnt^1][0] + dp[cnt^1][1] + dp[cnt^1][4];
  cout << ans % mod << endl;
  return 0;
}

  

时间: 2024-08-02 03:38:36

CodeForces 404D Minesweeper 1D (DP)的相关文章

Codeforces 41D Pawn 简单dp

题目链接:点击打开链接 给定n*m 的矩阵 常数k 下面一个n*m的矩阵,每个位置由 0-9的一个整数表示 问: 从最后一行开始向上走到第一行使得路径上的和 % (k+1) == 0 每个格子只能向或走一步 求:最大的路径和 最后一行的哪个位置作为起点 从下到上的路径 思路: 简单dp #include <cstdio> #include <algorithm> #include<iostream> #include<string.h> #include &

CodeForces 18E Flag 2 dp

题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h> #include<queue> #include<string> #include<stdlib.h> #include<a

CodeForces 19B Checkout Assistant dp

题目链接:点击打开链接 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf 115292150460684697

LeetCode &quot;Longest Palindromic Substring&quot; - 1D DP

2D DP is an intuitive solution of course, but I got an MLE error, so I simplified it into a 1D DP: class Solution { public: void goDp(vector<int> &dp, int &maxLen, int &is, int &ie, int startLen, int len, string &s) { for(int ile

Neko and Aki&#39;s Prank CodeForces - 1152D (括号序列,dp)

大意: 将所有长度为2*n的合法括号序列建成一颗trie树, 求trie树上选出一个最大不相交的边集, 输出边集大小. 最大边集数一定不超过奇数层结点数. 这个上界可以通过从底层贪心达到, 所以就转化为求奇数层结点数. 然后就dp求出前$i$为'('比')'多j个的方案数, 奇数层且合法的时候统计一下贡献即可. #include <iostream> #include <iostream> #include <algorithm> #include <cstdio

codeforces 148D 【概率dp】

题目链接: codeforces 148D Bag of mice 题意:一个包里面有w只白老鼠和b只黑老鼠,公主与龙依次从包中拿老鼠,每次取一只,当龙拿时还会从包中溜走一只,先拿到老鼠的获胜,当背包中没老鼠时且之前没人拿到白老鼠则龙获胜,问公主获胜的概率是多少. 题解: 设dp[i][j]为背包中有i只白老鼠j只黑老鼠时公主获胜的概率 则公主获胜的情况分成三种: 1.直接拿到白老鼠 p1=i/(i+j) 2.公主拿到黑老鼠,龙拿到黑老鼠,逃跑一只黑老鼠 p2=(j/(i+j)) ((j-1)/

[Codeforces 1295F]Good Contest(DP+组合数学)

[Codeforces 1295F]Good Contest(DP+组合数学) 题面 有一个长度为\(n\)的整数序列,第\(i\)个数的值在\([l_i,r_i]\)中随机产生.问这个序列是一个不上升序列的概率(模\(998244353\)意义下). \(n \leq 50,l_i,r_i \leq 998244351\) 分析 和[APIO2016]划艇几乎一模一样.可惜比赛的时候时间不够. 首先把问题转化成求最长不上升序列的数量. 我们把这些区间离散化,分割成两两之间不互相覆盖的若干个区间

Codeforces 404D [DP]

/* 我是一个习惯后悔,但是没办法忍受内疚感的二货== 这题是个无脑dp,但是比赛大概20min没出...其实最后5min我好好想想简单化边界条件,可以出的. 题意: 给你一个长度为1e6的由?*01四种字符组成的字符串,类似扫雷,?代表当前不确定,0代表当前无雷,并且 两边无雷,1代表当前五雷且两边有一个雷,2同样的,问当所有格子已知以后一共有多少种可能的局面. 思路: 首先想到的是,这个问题无后效性,而当前位置的合法方式只与它之前的两位有关. 所以dp的思路也是显而易见的,即dp[i][j]

codeforces Minesweeper 1D

题意:就是挖地雷,给你一个字符串,‘*’代表地雷,‘1’代表在它的周围有1个地雷,‘2’代表在左右都有个地雷,‘?’代表不确定是不是地雷,可以是1,2,*,问你最后有几种方式确定所有的的地雷. 思路:dp[i][0] 代表次位置为0,dp[i][1]代表左边有地雷,dp[i][2]代表右边有地雷,dp[i][3]代表左右都有,dp[i][4]代表此位置为地雷. 1 #include <cstdio> 2 #include <cstring> 3 #include <algor