今天517盯着我说:我觉得今天你会被抽到, 然后~我就真的被抽到了,还是一道不会的题。。。
有两堆牌,每堆牌有n张牌,alice和bob轮流从某堆牌的最上面或者最下面取牌,牌上面写的分数会被加到他们对应的总分里,alice和bob都是绝顶聪明的,假如alice先取牌,最终他的得分是多少。
输入格式:
第一行输入一个整数n
接下来两行每行包含n个数,分别表示两堆牌。
输出格式:
输出一个整数,表示alice的得分
样例输入:
3
10 100 20
2 4 3
105
#include<bits/stdc++.h>
using namespace std;
int n, a[22], b[22], dp[22][22][22][22], last[22][22][22][22];
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; i++)
scanf("%d", &b[i]);
for(int i = 1; i < n; i++)
for(int j = 1; j < n; j++){
for(int xa = 1; xa <= n - i; xa++){
for(int xb = 1; xb <= n - i; xb++){
int ya = xa + i, yb = xb + i;
if(last[xa+1][ya][xb][yb] == 0) dp[xa][ya][xb][yb] = a[xa];
if(last[xa+1][ya][xb][yb] == 1)
if(dp[xa][ya][xb][yb] < dp[xa + 2][ya][xb][yb] + a[xa])
dp[xa][ya][xb][yb] = dp[xa + 2][ya][xb][yb] + a[xa], last[xa][ya][xb][yb] = 1;
if(last[xa+1][ya][xb][yb] == 2)
if(dp[xa][ya][xb][yb] < dp[xa + 1][ya - 1][xb][yb] + a[xa])
dp[xa][ya][xb][yb] = dp[xa + 1][ya - 1][xb][yb] + a[xa], last[xa][ya][xb][yb] = 1;
if(last[xa+1][ya][xb][yb] == 3)
if(dp[xa][ya][xb][yb] < dp[xa + 1][ya][xb + 1][yb] + a[xa])
dp[xa][ya][xb][yb] = dp[xa + 1][ya][xb + 1][yb] + a[xa], last[xa][ya][xb][yb] = 1;
if(last[xa+1][ya][xb][yb] == 4)
if(dp[xa][ya][xb][yb] < dp[xa + 1][ya][xb][yb - 1] + a[xa])
dp[xa][ya][xb][yb] = dp[xa + 1][ya][xb][yb - 1] + a[xa], last[xa][ya][xb][yb] = 1;
if(last[xa][ya - 1][xb][yb] == 0) dp[xa][ya][xb][yb] = a[ya];
if(last[xa][ya - 1][xb][yb] == 1)
if(dp[xa][ya][xb][yb] < dp[xa + 1][ya - 1][xb][yb] + a[ya])
dp[xa][ya][xb][yb] = dp[xa + 1][ya - 1][xb][yb] + a[ya], last[xa][ya][xb][yb] = 2;
if(last[xa][ya - 1][xb][yb] == 2)
if(dp[xa][ya][xb][yb] < dp[xa][ya - 2][xb][yb] + a[ya])
dp[xa][ya][xb][yb] = dp[xa][ya - 2][xb][yb] + a[ya], last[xa][ya][xb][yb] = 2;
if(last[xa][ya - 1][xb][yb] == 3)
if(dp[xa][ya][xb][yb] < dp[xa][ya - 1][xb + 1][yb] + a[ya])
dp[xa][ya][xb][yb] = dp[xa][ya - 1][xb + 1][yb] + a[ya], last[xa][ya][xb][yb] = 2;
if(last[xa][ya - 1][xb][yb] == 4)
if(dp[xa][ya][xb][yb] < dp[xa][ya - 1][xb][yb - 1] + a[ya])
dp[xa][ya][xb][yb] = dp[xa][ya - 1][xb][yb - 1] + a[ya], last[xa][ya][xb][yb] = 2;
if(last[xa][ya][xb + 1][yb] == 0) dp[xa][ya][xb][yb] = b[xb];
if(last[xa][ya][xb + 1][yb] == 1)
if(dp[xa][ya][xb][yb] < dp[xa + 1][ya][xb + 1][yb] + b[xb])
dp[xa][ya][xb][yb] = dp[xa + 1][ya][xb + 1][yb] + b[xb], last[xa][ya][xb][yb] = 3;
if(last[xa][ya][xb + 1][yb] == 2)
if(dp[xa][ya][xb][yb] < dp[xa][ya - 1][xb + 1][yb] + b[xb])
dp[xa][ya][xb][yb] = dp[xa][ya - 1][xb + 1][yb] + b[xb], last[xa][ya][xb][yb] = 3;
if(last[xa][ya][xb + 1][yb] == 3)
if(dp[xa][ya][xb][yb] < dp[xa][ya][xb + 2][yb] + b[xb])
dp[xa][ya][xb][yb] = dp[xa][ya][xb + 2][yb] + b[xb], last[xa][ya][xb][yb] = 3;
if(last[xa][ya][xb + 1][yb] == 4)
if(dp[xa][ya][xb][yb] < dp[xa][ya][xb + 1][yb - 1] + b[xb])
dp[xa][ya][xb][yb] = dp[xa][ya][xb + 1][yb - 1] + b[xb], last[xa][ya][xb][yb] = 3;
if(last[xa][ya][xb][yb - 1] == 0) dp[xa][ya][xb][yb] = b[yb];
if(last[xa][ya][xb][yb - 1] == 1)
if(dp[xa][ya][xb][yb] < dp[xa + 1][ya][xb][yb - 1] + b[yb])
dp[xa][ya][xb][yb] = dp[xa + 1][ya][xb][yb - 1] + b[yb], last[xa][ya][xb][yb] = 4;
if(last[xa][ya][xb][yb - 1] == 2)
if(dp[xa][ya][xb][yb] < dp[xa][ya - 1][xb][yb - 1] + b[yb])
dp[xa][ya][xb][yb] = dp[xa][ya - 1][xb][yb - 1] + b[yb], last[xa][ya][xb][yb] = 4;
if(last[xa][ya][xb][yb - 1] == 3)
if(dp[xa][ya][xb][yb] < dp[xa][ya][xb + 1][yb - 1] + b[yb])
dp[xa][ya][xb][yb] = dp[xa][ya][xb + 1][yb - 1] + b[yb], last[xa][ya][xb][yb] = 4;
if(last[xa+1][ya][xb][yb] == 4)
if(dp[xa][ya][xb][yb] < dp[xa][ya][xb][yb - 2] + b[yb])
dp[xa][ya][xb][yb] = dp[xa][ya][xb][yb - 2] + b[yb], last[xa][ya][xb][yb] = 4;
}
}
}
for(int i = 1; i < n; i++)
for(int j = 1; j < n; j++)
for(int xa = 1; xa <= n - i; xa++)
for(int xb = 1; xb <= n - i; xb++) {
int ya = xa + i, yb = xb + i;
printf("%d %d %d %d %d\n", xa, ya, xb, yb, dp[xa][ya][xb][yb]);
}
printf("%d", dp[1][n][1][n]);
return 0;
}
然后,我就在众目睽睽之下写下了这样的一份代码:别复制那连样例也过不去
所以进过各种思考(tijie)我终于贺到了一份简短的代码:
我们可以用前缀和快速的处理出区间的和, 因为每一个人都是绝顶聪明的,所以他们都会选择最利于自己的一步:
dp[1][n][1][n] = max(sum - 四个卡片中取一个后的dp值 + 这个值)
可以用记忆化搜索:附上贺的代码::
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
int num1[22];
int num2[22];
int sum1[22];
int sum2[22];
int ans[22][22][22][22];
int n;
int dfs(int i,int j,int k,int h)
{
int sum=sum1[j]-sum1[i-1]+sum2[h]-sum2[k-1];
if(ans[i][j][k][h]!=0)
return ans[i][j][k][h];
int ans1=0;
if(i<j){
ans1=max(ans1,sum-dfs(i+1,j,k,h));
ans1=max(ans1,sum-dfs(i,j-1,k,h));
}
if(i==j) ans1=max(ans1,sum-dfs(i+1,j,k,h));
if(k<h)
{
ans1=max(ans1,sum-dfs(i,j,k+1,h));
ans1=max(ans1,sum-dfs(i,j,k,h-1));
}
if(k==h) ans1=max(ans1,sum-dfs(i,j,k+1,h));
return ans[i][j][k][h]=ans1;
}
int main()
{
int t;cin>>t;
while(t--)
{
memset(ans,0,sizeof ans);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",num1+i),sum1[i]=sum1[i-1]+num1[i];
for(int i=1;i<=n;i++)
scanf("%d",num2+i),sum2[i]=sum2[i-1]+num2[i];
cout<<dfs(1,n,1,n)<<'\n';
}
return 0;