递归超时的代码:
// Problem#: 1176
// Submission#: 2918390
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int A[1005];
int search(int l,int r)
{
int maxn,temp;
if (r-l==1) return A[l]>=A[r]?A[l]:A[r];
if (A[l+1]>=A[r])
maxn=search(l+2,r)+A[l];
else
maxn=search(l+1,r-1)+A[l];
if (A[l]>=A[r-1])
{
temp=search(l+1,r-1)+A[r];
return maxn>temp?maxn:temp;
}
else
{
temp=search(l,r-2)+A[r];
return maxn>temp?maxn:temp;
}
}
int main()
{
int n,i;
int counter=0;
while (1)
{
counter++;
scanf("%d",&n);
if (!n) break;
int total=0;
for (i=0;i<n;i++)
{
scanf("%d",&A[i]);
total+=A[i];
}
printf("In game %d, the greedy strategy might lose by as many as %d points.\n",counter,2*search(0,n-1)-total);
}
}
加个记忆化搜索AC:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int A[1005];
int dp[1005][1005];
int search(int l,int r)
{
if (dp[l][r]) return dp[l][r];
int maxn,temp;
if (r-l==1) return dp[l][r]=A[l]>=A[r]?A[l]:A[r];
if (A[l+1]>=A[r])
maxn=search(l+2,r)+A[l];
else
maxn=search(l+1,r-1)+A[l];
if (A[l]>=A[r-1])
{
temp=search(l+1,r-1)+A[r];
maxn=maxn>temp?maxn:temp;
}
else
{
temp=search(l,r-2)+A[r];
maxn=maxn>temp?maxn:temp;
}
return dp[l][r]=maxn;
}
int main()
{
int n,i;
int counter=0;
while (1)
{
counter++;
memset(dp,0,sizeof(dp));
scanf("%d",&n);
if (!n) break;
int total=0;
for (i=0;i<n;i++)
{
scanf("%d",&A[i]);
total+=A[i];
}
printf("In game %d, the greedy strategy might lose by as many as %d points.\n",counter,2*search(0,n-1)-total);
}
}
动态规划的写法:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int A[1005];
int dp[1005][1005];
int main()
{
int n,i,j;
int counter=0;
while (1)
{
counter++;
memset(dp,0,sizeof(dp));
scanf("%d",&n);
if (!n) break;
int total=0;
for (i=0;i<n;i++)
{
scanf("%d",&A[i]);
total+=A[i];
}
for (i=0;i<n-1;i++)
dp[i][i+1]=A[i]>A[i+1]?A[i]:A[i+1];
int l,r,maxn;
for (i=3;i<n;i+=2)
for (j=0;j+i<n;j++)
{
l=j;
r=j+i;
if (A[l+1]>=A[r])
maxn=A[l]+dp[l+2][r];
else
maxn=A[l]+dp[l+1][r-1];
if (A[l]>=A[r-1])
maxn=maxn>(A[r]+dp[l+1][r-1])?maxn:(A[r]+dp[l+1][r-1]);
else
maxn=maxn>(A[r]+dp[l][r-2])?maxn:(A[r]+dp[l][r-2]);
dp[l][r]=maxn;
}
printf("In game %d, the greedy strategy might lose by as many as %d points.\n",counter,2*dp[0][n-1]-total);
}
}
实际上动态规划和记忆化搜索的思想是一样的,对于这道题记忆化搜索要好写一些,而且避免了很多不必要的计算。