您的位置:首页
第七届省赛赛前交流赛部分题解
2017-06-15 10:13
183 查看
A题: Yougth's Game[Ⅲ]( 区间dp )
这是在省赛前热身赛出的题目,可能是题目中实用到博弈的思想,非常多人都在做,并且在尝试暴力。
可是没有人往dp的方向上想。
题目类型:动态规划+博弈分析:题意描写叙述的非常清楚,就是选择在两端取数,当前取的数不仅可以影响下一次的结果,并且可以影响后面的结果。
。
。又是一个求最优值,那么是不是可以往dp的方向上想了。区间dp定义状态dp[ i ] [ j ] 为从 i 到 j 上A的得分,那么B的得分就是sum(i,j)-dp[ i ] [ j ]转移方程 : dp[i][j]=max(dp[i][j],a[i]+(sum[j]-sum[i]-dp[i+1][j]));
表示区间i--j取第一个[b]dp[i][j]=max(dp[i][j],a[j]+(b[j-1]-b[i-1]-dp[i][j-1]));
表示区间i--j取最后一个[/b]
代码:
E:Yougth's Game[II]
题目类型:组合博弈
事实上就是一个sg函数,sg函数解说:解说
分析:题目能够抽象成一个取石子游戏,三堆石子x,y,x*y。那么就抽象成了经典的取石子游戏。
每次能够取得数目是给定的,谁最后取完谁赢。
求出三个数的sg值,然后异或就是ans
代码:
H题:合并游戏
题目类型:状态压缩动态规划
分析:给出每两个石子合并蹦出的金币,求全部石子合并之后蹦出的金币,分析能够发现不同的合并顺序会有不一样的结果。然后满足最优子结构的性质。那就是确定某几个石子合并的到的最大金币永远是确定的,那么我们能够用dp来求解。而这个题目恰好是一个从0到全部合并的一个过程。用二进制压缩来表示状态。
定义状态:dp【st】表示状态st中为1的合并起来的最大值
状态转移方程:dp[state-(1<<j)]=max(dp[state-(1<<j)], dp[state]+a[i][j]);(每次都从 i 为1的点转移过来)
代码:
这是在省赛前热身赛出的题目,可能是题目中实用到博弈的思想,非常多人都在做,并且在尝试暴力。
可是没有人往dp的方向上想。
题目类型:动态规划+博弈分析:题意描写叙述的非常清楚,就是选择在两端取数,当前取的数不仅可以影响下一次的结果,并且可以影响后面的结果。
。
。又是一个求最优值,那么是不是可以往dp的方向上想了。区间dp定义状态dp[ i ] [ j ] 为从 i 到 j 上A的得分,那么B的得分就是sum(i,j)-dp[ i ] [ j ]转移方程 : dp[i][j]=max(dp[i][j],a[i]+(sum[j]-sum[i]-dp[i+1][j]));
表示区间i--j取第一个[b]dp[i][j]=max(dp[i][j],a[j]+(b[j-1]-b[i-1]-dp[i][j-1]));
表示区间i--j取最后一个[/b]
代码:
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N = 1200; int a ,dp ,n; int b ; int main() { while(~scanf("%d",&n)&&n) { b[0]=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); b[i]=b[i-1]+a[i]; } for(int l=1;l<=n;l++) { for(int i=1,j=l;j<=n;i++,j++) { dp[i][j]=-99999999; dp[i][j]=max(dp[i][j],a[i]+(b[j]-b[i]-dp[i+1][j])); dp[i][j]=max(dp[i][j],a[j]+(b[j-1]-b[i-1]-dp[i][j-1])); } } printf("%d\n",dp[1] -(b -dp[1] )); } return 0; }
E:Yougth's Game[II]
题目类型:组合博弈
事实上就是一个sg函数,sg函数解说:解说
分析:题目能够抽象成一个取石子游戏,三堆石子x,y,x*y。那么就抽象成了经典的取石子游戏。
每次能够取得数目是给定的,谁最后取完谁赢。
求出三个数的sg值,然后异或就是ans
代码:
#include<stdio.h> #include<string.h> #include <string> #include <iostream> using namespace std; const int N = 10008; int s[108],t; int sg ; bool hash ; void sg_solve(int *s,int t,int N) //N求解范围 S[]数组是能够每次取的值。t是s的长度。 { int i,j; memset(sg,0,sizeof(sg)); for(i=1;i<=N;i++) { memset(hash,0,sizeof(hash)); for(j=0;j<t;j++) if(i - s[j] >= 0) hash[sg[i-s[j]]] = 1; for(j=0;j<=N;j++) if(!hash[j]) break; sg[i] = j; } } int main() { int x,y; while(~scanf("%d%d",&x,&y)) { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&s[i]); sg_solve(s,n,N); if((sg[x]^sg[y]^sg[x*y])==0) printf("Yougth is best\n"); else printf("No\n"); } return 0; }
H题:合并游戏
题目类型:状态压缩动态规划
分析:给出每两个石子合并蹦出的金币,求全部石子合并之后蹦出的金币,分析能够发现不同的合并顺序会有不一样的结果。然后满足最优子结构的性质。那就是确定某几个石子合并的到的最大金币永远是确定的,那么我们能够用dp来求解。而这个题目恰好是一个从0到全部合并的一个过程。用二进制压缩来表示状态。
定义状态:dp【st】表示状态st中为1的合并起来的最大值
状态转移方程:dp[state-(1<<j)]=max(dp[state-(1<<j)], dp[state]+a[i][j]);(每次都从 i 为1的点转移过来)
代码:
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N = 12; int a ,dp[1<<N]; int main() { int n; while(~scanf("%d",&n)&&n) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); memset(dp,0,sizeof(dp)); for(int state=(1<<n); state>=0; state--) { for(int i=0; i<n; i++) //枚举初始合并点 { if(state&(1<<i)) continue; for(int j=0; j<n; j++) //跟哪一个合并 { if(!(state&(1<<j))) continue; if(i==j) continue; int newstate=state-(1<<j); dp[newstate]=max(dp[newstate], dp[state]+a[i][j]); } } } int maxnum=0; for(int i=0; i<(1<<n); i++) maxnum=max(maxnum, dp[i]); printf("%d\n", maxnum); } return 0; }
相关文章推荐
- 第七届省赛赛前交流赛部分题解
- 2016第七届蓝桥杯省赛C组试题及部分答案
- 2016山东省第七届ACM省赛-部分题解
- 算法笔记_123:蓝桥杯第七届省赛(Java语言B组部分习题)试题解答
- 第七届 蓝桥杯 c/c++ B组 省赛 (8)——四平方和
- 第七届省赛C语言A组7题-剪邮票
- CSU1102 多连块拼图 湖南第七届省赛
- 算法笔记_121:蓝桥杯第六届省赛(Java语言C组部分习题)试题解答
- 第七届蓝桥杯Java语言B组真题(省赛)
- 2010年9月22号校内ACM省赛前模拟赛教师总结外加部分结题报告
- 共享雅虎,交流乐趣---第四部分
- 山东省第七届ACM省赛 Triple Nim
- 摩托罗拉部分C++面试题,交流
- 2016 蓝桥杯 C/C++ B组 省赛 练习题(上半部分)
- 2016年第七届蓝桥杯c/c++省赛B组
- hunnuoj11186—报数(湖南第七届省赛)
- 第七届蓝桥杯B组省赛--方块分割
- 2016第七届蓝桥杯 C/C++省赛第9题 交换瓶子
- 实际工作中遇到的技术难题与大家交流(工作流条件表达式计算部分),希望技术高手能给于指点
- 共享雅虎,交流乐趣---最后部分