UVa10891 Game of Sum(dp)
2017-10-08 09:34
375 查看
简述:
n的序列,两人轮流从两端取数,
两人都选择最优策略,求两人的得分之差
分析:
一开始觉得是一道博弈
但是可以用dp解决的
这就和Tyvj上的硬币游戏有异曲同工之妙
因为只能取一个连续的区间
所以剩下的一定是原序列中的一个连续区间
这就指引我们往区间dp的方向上想
设计状态:f[i][j]表示现在剩下i~j的序列,先手的最高得分
f[i][j]=sum(i,j)-min{f[i+1][j],f[i+2][j],…,f[j][j],f[i][j-1],f[i][j-2],…,f[i][i],0}
注意,0表示先手全部取走
最后答案是
f[1]
-(sum(1,n)-f[1]
)
时间复杂度O(n^3)
我们发现转移的时候,min值的计算是很有规律的
所以我们记
g1[i][j]=min{f[i][j],f[i+1][j],f[i+2][j],…,f[j][j]}
g2[i][j]=min{f[i][j],f[i][j-1],f[i][j-2],…,f[i][i]}
转移就变成了:
f[i][j]=sum(i,j)-min{g1[i+1][j],g2[i][j-1],0}
不要忘了0
g1和g2的转移也很好维护
g1[i][j]=min(g1[i+1][j],f[i][j])
g2[i][j]=min(g2[i][j-1],f[i][j])
这样优化之后,时间复杂度就降到了n^2
n的序列,两人轮流从两端取数,
两人都选择最优策略,求两人的得分之差
分析:
一开始觉得是一道博弈
但是可以用dp解决的
这就和Tyvj上的硬币游戏有异曲同工之妙
因为只能取一个连续的区间
所以剩下的一定是原序列中的一个连续区间
这就指引我们往区间dp的方向上想
设计状态:f[i][j]表示现在剩下i~j的序列,先手的最高得分
f[i][j]=sum(i,j)-min{f[i+1][j],f[i+2][j],…,f[j][j],f[i][j-1],f[i][j-2],…,f[i][i],0}
注意,0表示先手全部取走
最后答案是
f[1]
-(sum(1,n)-f[1]
)
时间复杂度O(n^3)
tip
当面前只有一个数的时候,必须取//这里写代码片 #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int INF=1e9; const int N=110; int n; int sum ; int f ; void dp() { int i,j,k; memset(f,0,sizeof(f)); for (int i=1;i<=n;i++) f[i][i]=sum[i]-sum[i-1]; //必须取数 for (int i=n;i>=1;i--) for (int j=i+1;j<=n;j++) { int minn=0; for (k=i;k<j;k++) { minn=min(minn,f[i][k]); minn=min(minn,f[k+1][j]); } f[i][j]=sum[j]-sum[i-1]-minn; } printf("%d\n",f[1] -(sum -f[1] )); } int main() { scanf("%d",&n); while (n) { sum[0]=0; for (int i=1;i<=n;i++) scanf("%d",&sum[i]),sum[i]+=sum[i-1]; dp(); scanf("%d",&n); } return 0; }
然而
我们还可以让时间复杂去更优一点我们发现转移的时候,min值的计算是很有规律的
所以我们记
g1[i][j]=min{f[i][j],f[i+1][j],f[i+2][j],…,f[j][j]}
g2[i][j]=min{f[i][j],f[i][j-1],f[i][j-2],…,f[i][i]}
转移就变成了:
f[i][j]=sum(i,j)-min{g1[i+1][j],g2[i][j-1],0}
不要忘了0
g1和g2的转移也很好维护
g1[i][j]=min(g1[i+1][j],f[i][j])
g2[i][j]=min(g2[i][j-1],f[i][j])
这样优化之后,时间复杂度就降到了n^2
void dp() { int i,j,k; for (int i=1;i<=n;i++) { f[i][i]=sum[i]-sum[i-1]; g1[i][i]=f[i][i]; g2[i][i]=f[i][i]; } for (i=n;i>=1;i--) for (j=i+1;j<=n;j++) { int minn=0; minn=min(minn,g1[i+1][j]); minn=min(minn,g2[i][j-1]); f[i][j]=sum[j]-sum[i-1]-minn; g1[i][j]=min(g1[i+1][j],f[i][j]); g2[i][j]=min(g2[i][j-1],f[i][j]); } printf("%d\n",f[1] -(sum -f[1] )); }
相关文章推荐
- UVA 10891 Game of Sum (区间DP)
- UVA 10891 Game of Sum(区间DP)
- uva10891 Game of Sum 博弈区间dp
- UVA - 10891 Game of Sum(区间dp)
- uva_10891 - Game of Sum( 博弈区间DP )
- UVA 10891 Game of Sum(区间DP)
- Uva 10891 - Game of Sum ( 区间dp )
- UVA - 10891 Game of Sum(记忆化搜索 区间dp)
- UVA 10891 Game of Sum(区间DP)
- uva 10891 Game of Sum (DP水题)
- UVA 10891 - Game of Sum(区间dp)
- uva 10891 - Game of Sum(博弈,区间dp)
- Uva 10891 Game of Sum(区间DP)
- UVA 10891 Game of Sum(区间DP)
- UVA 10891 Game of Sum(区间DP)
- UVa UVA 10891 Game of Sum (区间DP)
- UVA 10891 Game of Sum(DP)
- UVA 10891 Game of Sum(区间DP)
- UVA 10891 Game of Sum 博弈DP -
- UVA 10891 Game of Sum(区间DP)