【动态规划】洛谷2019 OI春令营 - 普及组 作业
【P1464 Function】
【题解】
按照题目意思进行递归即可,但是过程中需要用到记忆化搜索。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[][][];
ll w(ll a,ll b,ll c){
if(a<=||b<=||c<=){return ;}
if(a>||b>||c>){return w(,,);}
if(a<b&&b<c){
if(dp[a][b][c-]==) dp[a][b][c-]=w(a,b,c-);
if(dp[a][b-][c-]==) dp[a][b-][c-]=w(a,b-,c-);
if(dp[a][b-][c]==) dp[a][b-][c]=w(a,b-,c);
return dp[a][b][c]=dp[a][b][c-]+dp[a][b-][c-]-dp[a][b-][c];
}else{
if(dp[a-][b][c]==)dp[a-][b][c]=w(a-,b,c);
if(dp[a-][b-][c]==)dp[a-][b-][c]=w(a-,b-,c);
if(dp[a-][b][c-]==)dp[a-][b][c-]=w(a-,b,c-);
if(dp[a-][b-][c-]==)dp[a-][b-][c-]=w(a-,b-,c-);
return dp[a][b][c]
=dp[a-][b][c]
+dp[a-][b-][c]
+dp[a-][b][c-]
-dp[a-][b-][c-];
}
}
int main()
{
ll a,b,c;
while(~scanf("%lld%lld%lld",&a,&b,&c)){
if(a==-&&b==-&&c==-){
break;
}
ll ans=w(a,b,c);
printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,ans);
}
return ;
}
【P1002 过河卒】
【题解】
其实就是马的位置和马口的位置方案为0,无法转移,其他情况照常即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
ll dp[N][N];
int dir[][] = {
{-,-} , {-,},
{-,-}, {-,},
{,},
{,-}, {,},
{,-}, {,}
};
int main()
{
int n,m,x,y;
cin >> n >> m >> x >> y ;
n ++ , m ++ , x ++ , y ++ ;
dp[][] = ;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if( i == && j == ) continue ;
bool f = true;
for(int k=;k<;k++){
if( i == x + dir[k][] && j == y + dir[k][] )
f = false ;
}
if( f )
dp[i][j] = dp[i-][j] + dp[i][j-];
}
} printf("%lld\n",dp[n][m]);
return ; }
【P1004 方格取数】
【题解】
这个题目和传纸条一样,开4维,分别枚举两个人在两个维度上同时跑动获取最大值的情况综合即可,
这个题目比传纸条更简单的是一个点可以经过两次 并且确保两个维度的曼哈顿距离相同。
#include<bits/stdc++.h>
using namespace std;
const int N = ;
int G[N][N],n,u,v,w;
int dp[N][N][N][N];
int main()
{
ios_base :: sync_with_stdio(false);
cin.tie(NULL),cout.tie(NULL); cin >> n ; while ( cin >> u >> v >> w , (u+v+w) ){
G[u][v] = w ;
} for(int x1=;x1<=n;x1++){
for(int y1=;y1<=n;y1++){
for(int x2=;x2<=n;x2++){
for(int y2=;y2<=n;y2++){ if( !( x1 == n && y1 == n ) && ( x1 + y1 != x2 + y2 ) )
continue ; int tmp = ;
/*if( ( !(x1 == x2 && y1 == y2) ) ||
( (x1 == x2 && y1 == y2) && (x1 == n && y1 == n) ) ){
*/
tmp = max( tmp , dp[x1-][y1][x2-][y2] );
tmp = max( tmp , dp[x1-][y1][x2][y2-] );
tmp = max( tmp , dp[x1][y1-][x2-][y2] );
tmp = max( tmp , dp[x1][y1-][x2][y2-] ); dp[x1][y1][x2][y2] = tmp + G[x1][y1] + G[x2][y2] ;
if( x1 == x2 && y1 == y2 ){
dp[x1][y1][x2][y2] = dp[x1][y1][x2][y2] - G[x1][y1];
}
//}
}
}
}
}
cout << dp[n][n][n][n] << endl;
return ;
}
【P1006 传纸条】
#include<bits/stdc++.h>
using namespace std;
const int N = ;
int dp[N][N][N][N],G[N][N];
int n,m;
int main()
{
ios_base :: sync_with_stdio(false);
cin.tie(NULL) , cout.tie(NULL);
cin >> n >> m ;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
cin >> G[i][j] ;
for(int x1=;x1<=n;x1++){
for(int y1=;y1<=m;y1++){
for(int x2=;x2<=n;x2++){
for(int y2=;y2<=m;y2++){
//如果没有达到终点,那么左下角是(x1,y1),右上角就是(x2,y2) //这句话就是,如果过程中出现 步数不相符的情况,也就是说两者同时跑。不出现一个走10步,另一个走1步
//if( !( x1 == n && y1 == m ) && ( x1 < x2 && y1 < y2 ) )
if( !( x1 == n && y1 == m ) && ( x1 + y1 != x2 + y2 ) )
continue ; // 更新的时候,过程中 不能存在两者都在同一个点的情况。
if( ( x1 == n && y1 == m && x1==x2 && y1==y2 )
|| !( x1 == x2 && y1 == y2) ){
int tmp = ;
tmp = max ( tmp , dp[x1-][y1][x2-][y2] );
tmp = max ( tmp , dp[x1-][y1][x2][y2-] );
tmp = max ( tmp , dp[x1][y1-][x2-][y2] );
tmp = max ( tmp , dp[x1][y1-][x2][y2-] ); dp[x1][y1][x2][y2] = tmp + G[x1][y1] + G[x2][y2] ;
}
}
}
}
} cout << dp[n][m][n][m] << endl;
return ;
}
【P1005 矩阵取数游戏】
【题意】
每一行拿m次,然后再拿n行,每一行的拿法都一样,拿左右端次序和对应的价值乘积最大。
考虑区间dp。
f[L][R],在取L,R这一段之前 两端取得的最大值
f[L][R] = max{ f[L-1][R] +a[L] * 2 ^(m+L-R-1) , f[L][R+1] + a[R] * 2^(m+L-R-1) }
最后还需要对于每一个单独的f[i][i]拿一遍,因为状态转移没有考虑长度为1的情况。
过程中还需要用到高精度,
高精度需要:
1、高精度+高精度
2、高精度×低精度
3、max{ 高精度,高精度}
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e4 ; //
const int N = ; typedef struct High_precision{
int Len , p[N] ;
High_precision() {
Len = ;
memset( p , , sizeof p) ;
} void Print(){
printf("%d",p[Len]);
for(int i = Len- ; i >= ;i--){
printf("%04d",p[i]);
}
puts("");
}
}Hp; Hp operator + (const Hp& A , const Hp& B ){
int Len = max( A.Len , B.Len );
Hp C ;
int Carry = ;
for(int i= ; i<=Len ; i++ ){
C.p[i] = ( A.p[i] + B.p[i] + Carry ) ;
Carry = (C.p[i]) / mod ;
C.p[i] = C.p[i] % mod ;
}
C.Len = Len ;
if( Carry ){
C.p[++C.Len] = Carry ;
}
return C ;
} Hp operator * (const Hp& A , const int B ){
Hp C ;
int Len = A.Len ;
int Carry = ;
for(int i = ; i <= Len ; i ++ ){
C.p[i] = A.p[i] * B + Carry ;
Carry = C.p[i] / mod ;
C.p[i] = C.p[i] % mod ;
//C.p[i] = ( A.p[i] * B + Carry ) % mod ;
//Carry = ( A.p[i] * B + Carry ) / mod ;
}
C.Len = A.Len ;
while( Carry > ){
C.p[++C.Len] = Carry % mod ; Carry = Carry / mod ;
} return C ;
} Hp Max( const Hp& A, const Hp& B ){
int LA = A.Len , LB = B.Len ;
if( A.Len > B.Len ) return A ;
else if( B.Len > A.Len ) return B ;
for(int i=A.Len ; i>=;i--){
if( A.p[i] > B.p[i] ) return A ;
else if( B.p[i] > A.p[i] ) return B ;
}
return A ;
} Hp f[N][N] , Base[N] ;
int a[N] ;
int n,m; void Init(){
Base[].p[] = ;
Base[].Len = ;
for(int i=;i<=m+;i++)
Base[i] = Base[i-] * ; } int main()
{ scanf("%d%d",&n,&m);
Hp Ans , tmp ; Init();
//Base[20].Print(); for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&a[j]);
f[j][j].p[] = a[j] ;
f[j][j].Len = ;
//f[j][j].Print();
//tmp = Max ( tmp , f[j][j] );
}
memset( f , , sizeof f );//别忘了 //cout << " ### " ; tmp.Print();
for( int L = ; L <= m ; L++ ){
for( int R = m ; R >= L ; R-- ){
f[L][R] = Max( f[L-][R] + Base[m+L-R-] * a[L-] , f[L][R] );
f[L][R] = Max( f[L][R+] + Base[m+L-R-] * a[R+] , f[L][R] );
}
}
tmp.Len = ;
tmp.p[] = ;
for( int j = ; j <= m ;j++ ){
tmp = Max ( tmp , f[j][j] + Base[m] * a[j] ) ;
} //cout << " ### " ; tmp.Print(); Ans = Ans + tmp ;
} Ans.Print();
return ;
} /*
2 3
1 2 3
3 4 2 */
【P1049 装箱问题】
【题解】01背包
#include<bits/stdc++.h>
using namespace std;
const int N = ;
int dp[N];
int main()
{
int V , n ;
cin >> V >> n ; for(int i=,v;i<=n;i++){
scanf("%d",&v);
for(int j=V;j>=v;j--){
dp[j] = max(dp[j],dp[j-v]+v);
}
}
printf("%d\n",V-dp[V]);
return ;
}
【P1541 乌龟棋】
【感受】
当我做这个题目的时候不得不佩服当初杨宗耀是真NB,可能大家都想不出来的,他都能做出来,当初我觉得他写的四维DP也太难想到了吧,后来就想到了,而且做出来了。我真的佩服至今。
【题解】
考虑四个维度每一个维度都用了多少张牌,然后通过状态转移过来即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
const int M = ;
int dp[M][M][M][M],a[N];
int n,m;
int main(){
scanf("%d%d",&n,&m); for(int i=;i<=n;i++) scanf("%d",&a[i]); dp[][][][] = a[] ;
int cnt = ;
int One = , Two = , Three = , Four = ;
for(int i=,w;i<=m;i++){
scanf("%d",&w);
if( w == ) One ++ ;
else if( w == ) Two ++ ;
else if( w == ) Three ++ ;
else if( w == ) Four ++ ;
}
for(int o=;o<=One;o++){
for(int t=;t<=Two;t++){
for(int th=;th<=Three;th++){
for(int f=;f<=Four ;f++){ int dis = + o + t* + th* + f* ;
if( f >= ){
dp[o][t][th][f] =
max( dp[o][t][th][f-] + a[dis]
, dp[o][t][th][f] );
}
if( th >= ){ dp[o][t][th][f] =
max( dp[o][t][th-][f] + a[dis]
, dp[o][t][th][f]);
}
if( t >= ){
dp[o][t][th][f] =
max( dp[o][t-][th][f] + a[dis]
, dp[o][t][th][f]);
}
if( o >= ){
dp[o][t][th][f] =
max( dp[o-][t][th][f] + a[dis]
, dp[o][t][th][f]);
}
}
}
}
}
printf("%d\n",dp[One][Two][Three][Four]);
return ;
}
【P1048 采药】
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+;
int dp[N];
int main()
{
int V,n;
cin >> V >> n ;
for(int i=,v,w;i<=n;i++){
cin >> v >> w ;
for(int j=V;j>=v;j--){
dp[j] = max( dp[j] , dp[j-v]+w);
}
}
cout << dp[V] << endl;
return ;
}
【动态规划】洛谷2019 OI春令营 - 普及组 作业的更多相关文章
- 【贪心】洛谷2019 OI春令营 - 普及组 作业
[P3817 小A的糖果 小A有N个糖果盒,第i个盒中有a[i]颗糖果. 小A每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中加起来都只有x颗或以下的糖果,至少得吃掉几颗糖. [贪 ...
- 【数据结构】洛谷2019 OI春令营 - 普及组 作业
[P3662][USACO17FEB]Why Did the Cow Cross the Road II S 求解连续的k个数的最大值,利用前缀和维护即可. #include<bits/stdc ...
- 【洛谷2019 OI春令营】期中考试
T68402 扫雷 题目链接:传送门 题目描述 扫雷,是一款单人的计算机游戏.游戏目标是找出所有没有地雷的方格,完成游戏:要是按了有地雷的方格,游戏失败.现在 Bob 正在玩扫雷游戏,你作为裁判要判断 ...
- 洛谷P1067 多项式输出 NOIP 2009 普及组 第一题
洛谷P1067 多项式输出 NOIP 2009 普及组 第一题 题目描述 一元n次多项式可用如下的表达式表示: 输入输出格式 输入格式 输入共有 2 行 第一行 1 个整数,n,表示一元多项式的次数. ...
- 动态规划 洛谷P1616 疯狂的采药
动态规划 洛谷P1616 疯狂的采药 同样也是洛谷的动态规划一个普及-的题目,接下来分享一下我做题代码 看到题目,没很认真的看数据大小,我就提交了我的代码: 1 //动态规划 洛谷P1616 疯狂的采 ...
- 动态规划 洛谷P1048 [NOIP2005 普及组] 采药
洛谷P1048 [NOIP2005 普及组] 采药 洛谷的一个谱架-的题目,考的是01背包问题,接下来分享一下我的题解代码. AC通过图: 我的代码: 1 //动态规划 洛谷P1048 [NOIP20 ...
- 动态规划 洛谷P4017 最大食物链计数——图上动态规划 拓扑排序
洛谷P4017 最大食物链计数 这是洛谷一题普及/提高-的题目,也是我第一次做的一题 图上动态规划/拓扑排序 ,我认为这题是很好的学习拓扑排序的题目. 在这题中,我学到了几个名词,入度,出度,及没有环 ...
- 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告
目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...
- 洛谷2019 3月月赛 T2
题干 洛谷同款 T2?(看似比T1简单些) 二维前缀和嘛?[多简单 我天天拿二维前缀和水DP] 这是前缀和的预处理 2333 处理出来所有的情况 某个地方要加上mod再%mod 如果没有这一步 那么 ...
随机推荐
- iOS UILabel镂空特效
http://stackoverflow.com/questions/18716751/drawing-a-path-with-subtracted-text-using-core-graphics ...
- 深入理解JVM虚拟机1:JVM内存的结构与永久代的消失
所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ...
- chrome-添加JSON-handler插件
1.访问http://jsonhandle.sinaapp.com/下载 2.谷歌访问 chrome://extensions/ 然后找到你下载的JSON-handle_0.5.2.crx文件,直 ...
- java实现哈夫曼树进行文件加解压
目录 1.哈夫曼树简述 2.构造树的节点 3.构造哈夫曼树的类(压缩) 4.构造哈夫曼树的类(解压) 5.整体工程文件(包括测试类) 6.结果 7.参考链接 1.哈夫曼树简述 给定n个权值作为n个叶子 ...
- opencv 检测人脸、人眼
This tutorial code’s is shown lines below. You can also download it from here . The second version ( ...
- golang 循环创建闭包 问题排查
][]string{ { { "邀请码是什么", "我没有邀请码", "这个邀请码我可以随便填吗", "邀请码可以填他的手机号吗& ...
- 一台java服务器可以跑多少个线程?
一台java服务器能跑多少个线程?这个问题来自一次线上报警如下图,超过了我们的配置阈值. 京东自研UMP监控分析 打出jstack文件,通过IBM Thread and Monitor Dump ...
- connections java.net.BindException: Address already in use_解决方案
一.问题描述 在Linux服务器(CentOS7系统)中配置并启动JMeter远程监控服务器资源所需的ServerAgent目录下的 startAgent.sh 文件时,系统出现异常提示,如 [roo ...
- utf-8的中文是一个字符占几个字节
utf-8的中文是一个字符占几个字节 英文字母和中文汉字在不同字符集编码下的字节数英文字母:·字节数 : 1;编码:GB2312 字节数 : 1;编码:GBK 字节数 : 1;编码:GB18030 字 ...
- 算法习题---4-4骰子涂色(UVa253)
一:题目 分别对两个骰子的六个面涂色r-红 b-蓝 g-绿,通过转动骰子,看两个骰子是不是一样的涂色方法 (一)题目详解 题目规定了正方体的六个面的序号:从1-,按照这个需要提供涂色序列 (二)案例展 ...