摸鱼(一)(状压dp)
/*
摸鱼
题意:
有一条路上有n个坑,每个坑里面有v[i]个鱼(1<=v[i]<=100),peter从这条路走过,每个坑只能摸一次,
peter可以选择摸或者不摸,每摸一个坑都可以得到一个摸鱼快感,摸鱼快感的大小等于
坑中鱼的数量,但是如果该坑的两侧都没有被摸的话,就可以得到这个坑的摸鱼快感的2倍,
现在给你坑的数量和每个坑中鱼的数量,让你求最大的摸鱼快感
(坑的数量小于等于1e6);
时间 1s;
*/
思路:
(1),我的状压dp这样表示
用dp[i][j]表示从前面位置到当前位置的能最大值(不记录后一个为的值,但是标记,后一个位置是否选择)(在考虑状态的情况下),我的每个i位置表示,其前面,后面以及本身位置的选择,
(000) (这三个位置都没有选择)dp[i][j] = vmax[i-2];
(001) (只选择前一个位置) dp[i][j] = (dp[i-1][2]) > (dp[i-1][3]) ? (dp[i-1][2]) : (dp[i-1][3]);
(010) (只选择当前位置)dp[i][j] = (dp[i-1][4] + 2 * v[i]) > (dp[i-1][4] + 2 * v[i]) ? (dp[i-1][5] + 2 * v[i]) : (dp[i-1][5] + 2 * v[i]);
(011) (不选择后一个位置)(dp[i-1][6] + v[i]) > (dp[i-1][7] + v[i]) ? (dp[i-1][6] + v[i]) : (dp[i-1][7] + v[i]);
(100)(只选择后一个位置)dp[i][j] = 0;
(101)(不选择当前位置)dp[i][j] = (dp[i-1][2]) > (dp[i-1][3]) ? (dp[i-1][2]) : (dp[i-1][3]);
(110)(不选择前一个位置)(dp[i-1][4]) > (dp[i-1][5]) ? (dp[i-1][4]) : (dp[i-1][5]);
(111)(都选择)dp[i][j] = (dp[i-1][6]) > (dp[i-1][7]) ? (dp[i-1][6]) : (dp[i-1][7]);
最后考虑一下边界就行了。
由于不是oj上的题,自己就打了一个代码,望大家检查错误。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long llu;
const int maxn = 1e6+5;
const ll inf = 0x3f3f3f3f3f3f;
ll v[maxn],dp[maxn][8],vmax[maxn];
int main()
{
int t;
scanf("%d",&t);
for (int i = 0;i<t;i++){
scanf ("%lld",&v[i]);
}
v[t] = 0;
ll maxx = -inf;
for (int i = 0;i<8;i++){
if(i == 0) dp[1][i] = 0;
if(i == 1) dp[1][i] = 2*v[0];
if(i == 2) dp[1][i] = 2*v[1];
if(i == 3) dp[1][i] = v[0] + v[1];
if(i == 4) dp[1][i] = 0;
if(i == 5) dp[1][i] = 2 * v[0];
if(i == 6) dp[1][i] = v[1];
if(i == 7) dp[1][i] = v[0] + v[1];
maxx = max(maxx,dp[1][i]);
vmax[1] = maxx;
}
vmax[0] = v[0]*v[0];
for (int i = 2;i<=t;i++){
maxx = -inf;
for (int j = 0;j<8;j++){
if(j == 0) dp[i][j] = vmax[i-2];
if(j == 1) dp[i][j] = (dp[i-1][2]) > (dp[i-1][3]) ? (dp[i-1][2]) : (dp[i-1][3]);
if(j == 2) dp[i][j] = (dp[i-1][4] + 2 * v[i]) > (dp[i-1][4] + 2 * v[i]) ? (dp[i-1][5] + 2 * v[i]) : (dp[i-1][5] + 2 * v[i]);
if(j == 3) dp[i][j] = (dp[i-1][6] + v[i]) > (dp[i-1][7] + v[i]) ? (dp[i-1][6] + v[i]) : (dp[i-1][7] + v[i]);
if(j == 4) dp[i][j] = 0;
if(j == 5) dp[i][j] = (dp[i-1][2]) > (dp[i-1][3]) ? (dp[i-1][2]) : (dp[i-1][3]);
if(j == 6) dp[i][j] = (dp[i-1][4]) > (dp[i-1][5]) ? (dp[i-1][4]) : (dp[i-1][5]);
if(j == 7) dp[i][j] = (dp[i-1][6]) > (dp[i-1][7]) ? (dp[i-1][6]) : (dp[i-1][7]);
maxx = maxx > dp[i][j] ? maxx : dp[i][j];
}
vmax[i] = maxx;
}
printf("%lld\n",vmax[t]);
return 0;
}