类似的是codeforces 208B
题意:在一个队列中,工作人员挑选队列头的三个人中的两个进行服务,最两个人服务的时间是两个任务的最大值,设计最优方案,使服务时间最短。
做法:划分状态,就已现在队列头的两个人为状态划分量。只要确定了头两个人,状态是一定的,不可能在第二人之后还存在空格,第二个人之后一定跟着一个人。把三种取人情况模拟一下即可。然后输出方案时,dfs即可,暴力匹配,看与哪一个一个状态匹配。
#include<cstdio>
#include<algorithm>
#define LMT 1002
using namespace std;
int dp[LMT][LMT],a[LMT],n;
int dfs(int i,int j)
{
if(dp[i][j])return dp[i][j];
if(j==n)return dp[i][j]=a[i];
if(j==n-1)return dp[i][j]=max(a[i],a[j]);
dp[i][j]=max(a[i],a[j])+dfs(j+1,j+2);
dp[i][j]=min(dp[i][j],max(a[i],a[j+1])+dfs(j,j+2));
dp[i][j]=min(dp[i][j],max(a[j],a[j+1])+dfs(i,j+2));
return dp[i][j];
}
void output(int i,int j)
{
if(j==n)
{
printf("%d\n",i+1);
return;
}
if(j==n-1)
{
printf("%d %d\n",i+1,j+1);
return;
}
if(dp[i][j]==max(a[i],a[j])+dp[j+1][j+2])
{
printf("%d %d\n",i+1,j+1);
output(j+1,j+2);
}
else if(dp[i][j]==max(a[i],a[j+1])+dp[j][j+2])
{
printf("%d %d\n",i+1,j+2);
output(j,j+2);
}
else if(dp[i][j]==max(a[j],a[j+1])+dp[i][j+2])
{
printf("%d %d\n",j+1,j+2);
output(i,j+2);
}
}
int main(void)
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
printf("%d\n",dfs(0,1));
output(0,1);
return 0;
}