Codeforces Round #363 (Div. 2) C. Vacations

题意:
小V的一天有三种状态,去sport,去contest,去relax,然后一天呢会有四种情况,0没有gym也没有contest,1没有gym有contest,2有gym没有contest,3有gym有contest。
还有一个约束条件就是不能持续的去sport两天,也不能连续持续进行context。
求一个最小的休息时间
思路:
一开始写了个递推。然后写到这一天是既可以sport又可以contest,就迷茫了。我不知道这一步的最优了,因为这一步不是断绝的,这一步会给下一步造成影响。不过我又想想能不能纯模拟啊,后来再仔细想想不行的,但是可以写成一个贪心的样子。搜索么?可以么?后来想想就是个dp[ i ][ j ]代表第 i 天干 j 事就好了。简单递推,dp。

DP代码1:

int dp[110][4];
int main()
{
    int temp;
    int n,i,state,j;
    scanf("%d",&n);
    //初始化;
    for(i=0;i<=n;i++)
        dp[i][0]=dp[i][1]=dp[i][2]=INF;
    dp[0][0]=dp[0][1]=dp[0][2]=0;
    //非常简便的递推;
    for(i=1;i<=n;i++){
        scanf("%d",&state);
        dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+1;
        if(state&1)
            dp[i][1]=min(dp[i-1][0],dp[i-1][2]);
        if(state&2)
            dp[i][2]=min(dp[i-1][0],dp[i-1][1]);
    }
    printf("%d
",min(dp[n][0],min(dp[n][1],dp[n][2])));
    return 0;
}

记忆化搜索

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const double eps=1e-6;
const double pi=acos(-1.0);
const int mod=998244353;
const int INF=0x3f3f3f3f;

const int N=1e2+10;
int d[500];
int n;
int dp[500][500];
//记忆化搜索,很好啊。
int solve(int i,int last)//0 1 2 3
{
    if(i==n)
        return 0;
    if(dp[i][last]!=-1)                 //如果已经访问过。就不需要再进行搜索。
        return dp[i][last];
    int ans=1000;
    ans=min(ans,solve(i+1,0)+1);        //休息。
    for(int state=1;state<=2;state++){
        if(state == last) continue;
        if(!(state&d[i])) continue;
        ans=min(ans,solve(i+1,state));  //不休息。
    }
    return dp[i][last]=ans;
}

int main()
{
    cin >> n;
    for(int i = 0; i < n; i++)
        cin >> d[i];
    memset(dp, -1, sizeof dp);
    cout << solve(0, 0) << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934421.html