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\n",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;
}