【动态规划】洛谷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 如果没有这一步 那么 ...
随机推荐
- FLUENT导入CHEMKIN机理的单位问题【转载】
转载自:http://blog.sina.com.cn/s/blog_4a0a8b5d0101pj3c.html CHEMKIN机理导入后,发现速率常数全变了,那么他们是怎样变化的呢? FLUENT中 ...
- 【python代码】linux 登陆网关
#!/usr/bin/env python import urllib2 url="http://10.3.8.211" data="DDDDD=2010111222&a ...
- Flask上下文源码分析(一)
flask中的上下文分两种,application context和request context,即应用上下文和请求上下文. 从名字上看,可能会有误解,认为应用上下文是一个应用的全局变量,所有请 ...
- [Ubuntu] A start job is running for...interfaces
CPU:RK3288 系统:Linux 移植 Ubuntu 16.04 到嵌入式平台,如果以太网有问题,在这里会耗时大约5分钟 开机后可以修改 Ubuntu 配置来缩短时间 打开下面的文件,可以看到最 ...
- HTTP的POST提交的四种常见消息主体格式
HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种.其中 POST 一般用来向服务端提交数据,本文 ...
- 开发WINDOWS服务程序
开发WINDOWS服务程序 开发步骤: 1.New->Other->Service Application 2.现在一个服务程序的框架已经搭起来了,打开Service1窗口,有几个属性说明 ...
- spring aop中aspect和advisor的区别
之前看到spring AOP配置aspect(切面)有两种方式,一种是利用注解的方式配置,一种是利用XML的方式配置. 我们的配置是这样的<aop:aspect>,还有另外一种<ao ...
- [Java复习] 设计模式 Design Pattern
设计模式的六大原则 1.开闭原则(Open Close Principle) 对扩展开放,对修改关闭. 2.里氏代换原则(Liskov Substitution Principle) 任何基类可以出现 ...
- 012-多线程-JUC集合-Queue-SynchronousQueue和LinkedTransferQueue
一.SynchronousQueue概述 SynchronousQueue是一个不存储元素的队列.每一个put操作必须等待一个take操作,否则不能继续添加元素. 它支持公平访问队列.默认情况下线程采 ...
- C# winform中使用Panel调节窗口变化是各控件的位置(转)
我的目的是在窗口上有些控件,在窗口大小变化时,上面的控件位置不动,大小也不动.下面的控件随着窗口的大小变化而变大. 做法是用两个panel,panelTop和panelFill.上面的控件都放到pan ...