【傳送門:BZOJ1806】
簡要題意:
有兩個礦洞,有三種食物,給出n個食物的配送順序,每個食物可以給任意一個礦洞,每個食物送到一個礦洞的收益是這個礦洞最近三次(包括送的那次)食物的種類數
請你經過合理的配置設定食物使得收益最大
題解:
水題DP
設f[i][t1][t2][t3][t4]為目前已經送了i個食物,且最近兩次給第一個礦洞送了第t1和t2種食物(t1比t2更早送),給第二個礦洞送了第t3和t4種食物(t3比t4更早送)能得到的最大收益
假如t1,t2,t3,t4為0,表示目前沒有送那麼多的餐
轉移想想就會了
然後這題卡空間。。
沒關系,滾動數組一下就好了
參考代碼:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
char st[110000];
int f[2][4][4][4][4];
int a[110000];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",st+1);
for(int i=1;i<=n;i++)
{
if(st[i]=='M') a[i]=1;
if(st[i]=='F') a[i]=2;
if(st[i]=='B') a[i]=3;
}
memset(f,-1,sizeof(f));
f[0][0][0][0][0]=0;
int now=0,last=1;
int ans=0;
for(int i=1;i<=n;i++)
{
now^=1;last^=1;
for(int t1=0;t1<=3;t1++)
{
for(int t2=0;t2<=3;t2++)
{
int d1=0;
if(t1!=0&&t2==0)
{
d1=1;if(t1!=a[i]) d1=2;
}
else if(t1==0&&t2!=0)
{
d1=1;if(t2!=a[i]) d1=2;
}
else if(t1!=0&&t2!=0)
{
if(t1==t2)
{
d1=1;if(t1!=a[i]) d1=2;
}
else
{
d1=2;if(t1!=a[i]&&t2!=a[i]) d1=3;
}
}
else d1=1;
for(int t3=0;t3<=3;t3++)
{
for(int t4=0;t4<=3;t4++)
{
int d2=0;
if(t3!=0&&t4==0)
{
d2=1;if(t4!=a[i]) d2=2;
}
else if(t3==0&&t4!=0)
{
d2=1;if(t4!=a[i]) d2=2;
}
else if(t3!=0&&t4!=0)
{
if(t3==t4)
{
d2=1;if(t3!=a[i]) d2=2;
}
else
{
d2=2;if(t3!=a[i]&&t4!=a[i]) d2=3;
}
}
else d2=1;
if(f[last][t1][t2][t3][t4]!=-1)
{
f[now][t2][a[i]][t3][t4]=max(f[now][t2][a[i]][t3][t4],f[last][t1][t2][t3][t4]+d1);
f[now][t1][t2][t4][a[i]]=max(f[now][t1][t2][t4][a[i]],f[last][t1][t2][t3][t4]+d2);
ans=max(ans,max(f[now][t2][a[i]][t3][t4],f[now][t1][t2][t4][a[i]]));
}
}
}
}
}
}
printf("%d\n",ans);
return 0;
}
轉載于:https://www.cnblogs.com/Never-mind/p/8883884.html