牛客动态规划1选做

1|0[NOIP2002]过河卒


题目链接

进行记忆化搜索,然后强制把马所在的点和控制的点赋值为 0

#include<bits/stdc++.h> #define int long long using namespace std; set<pair<int,int>> st; int f[25][25]; int calc( int x , int y ){ if( x == 0 && y == 0 ) return f[x][y] = 1; if( x < 0 || y < 0 ) return 0; if( st.count( {x,y} ) ) return 0; if( f[x][y] ) return f[x][y]; return f[x][y] = calc( x - 1 , y ) + calc( x , y - 1 ); } int32_t main() { int n , m , s , t; cin >> n >> m >> s >> t; st.insert( { s , t } ); st.insert( { s-1 , t-2 } ) ,st.insert( { s-1 , t+2 } ); st.insert( { s+1 , t-2 } ) ,st.insert( { s+1 , t+2 } ); st.insert( { s-2 , t-1 } ) ,st.insert( { s-2 , t+1 } ); st.insert( { s+2 , t-1 } ) ,st.insert( { s+2 , t+1 } ); cout << calc( n , m ) << "\n"; return 0; }

2|0[NOIP2008]传球游戏


题目链接

设状态f[i][j]表示第j次传球后,球在i手上的点方案数,则f[i][j]=f[i-1][j-1]+f[i+1][j-1]

#include<bits/stdc++.h> #define int long long using namespace std; const int N = 35; int f[N][N] , n , m; int32_t main() { cin >> n >> m; f[1][0] = 1; for( int j = 1 ; j <= m ; j ++ ){ f[1][j] = f[n][j-1] + f[2][j-1]; f[n][j] = f[1][j-1] + f[n-1][j-1]; for( int i = 2 ; i < n ; i ++ ) f[i][j] = f[i-1][j-1] + f[i+1][j-1]; } cout << f[1][m] << "\n"; return 0; }

3|0滑雪


题目链接

记忆化搜索一下,f[x][y]表示从(x,y)出发最远可以走多远。

每次只能从相邻且比当前低的点转移过来

#include<bits/stdc++.h> using namespace std; int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } const int N = 105; const int dx[] = { 0 , 0 , 1 , -1 } , dy[] = { 1 , -1 , 0 , 0 }; int n , m , h[N][N] , f[N][N] , res = INT_MIN; int dfs( int x , int y ){ if( x < 1 || y < 1 || x > n || y > m ) return 0; if( f[x][y] ) return f[x][y]; f[x][y] = 1; for( int i = 0 , fx , fy ; i < 4 ; i ++ ){ fx = x + dx[i] , fy = y + dy[i]; if( h[x][y] > h[fx][fy] ) f[x][y] = max( f[x][y] , dfs( fx , fy ) + 1 ); } return f[x][y]; } int32_t main() { n = read() , m = read(); for( int i = 1 ; i <= n ; i ++ ) for( int j = 1 ; j <= m ; j ++ ) h[i][j] = read(); for( int i = 1 ; i <= n ; i ++ ) for( int j = 1 ; j <= m ; j ++ ) res = max( res , dfs( i , j ) ); cout << res; return 0; }

4|0方块与收纳盒


https://ac.nowcoder.com/acm/contest/24213/1001

简单的斐波那契额数列

递推版

#include<bits/stdc++.h> #define ll long long using namespace std; int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } ll f[100]; int32_t main() { f[0] = f[1] = 1; for( int i = 2 ; i <= 80 ; i ++ ) f[i] = f[i-1] + f[i-2]; for( int t = read() , x ; t ; t -- ) x = read() , cout << f[x] << "\n"; return 0; }

递归版

#include<bits/stdc++.h> #define ll long long using namespace std; int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } ll f[100]; ll calc( int x ){ if( f[x] ) return f[x]; return f[x] = calc( x - 1 ) + calc( x - 2 ); } int32_t main() { f[0] = f[1] = 1; for( int t = read() , x ; t ; t -- ) x = read() , cout << calc(x) << "\n"; return 0; }

5|0舔狗舔到最后一无所有


https://ac.nowcoder.com/acm/contest/24213/1002

f[i]表示前i天的合法方案。

如果i天与i-1天不同,则有两种选择方法

如果i天与i-1天相同,就不能与i-2天相同,与i-2天不同有两种选择方法

所以f[i] = f[i-1] * 2+ f[i-2]*2

#include<bits/stdc++.h> #define int long long using namespace std; const int N = 1e5+5 , mod = 1e9+7; int f[N]; int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } int32_t main() { f[1] = 3 , f[2] = 9; for( int i =3 ; i < N ; i ++ ) f[i] = ( f[i-1] + f[i-2] ) % mod * 2 % mod; for( int t = read() , x ; t ; t -- ) x = read() , cout << f[x] << "\n"; return 0; }

6|0[NOIP2001]装箱问题


https://ac.nowcoder.com/acm/contest/24213/1017

f[i][j]表示前i个物品能否填满空间j这样就可以得到状态转移方程f[i][j] |= f[i-1][j-v]

然后可以通过倒序枚举的方式优化一维空间

#include <iostream> #include <string> #include <vector> using namespace std; const int N = 20005; bool f[N]; int main(){ int v , n; cin >> v >> n; f[0] = 1; for( int i = 1 , x ; i <= n ; i ++ ){ cin >> x; for( int i = v ; i >= x ; i -- ) f[i] |= f[i-x]; } for( int i = v ; i >= 0 ; i -- ) if( f[i] ) cout << v-i , exit(0); return 0; }

7|0可爱の星空


因为合并的时候肯定是尽可能接近的两个数合并才可以使话费尽可能的小,所以为了合成n必须先合成n/2,然后处理一下奇数的情况就好

#include<bits/stdc++.h> #define int long long using namespace std; int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } map< int , int > g; int f( int x ) { if( x == 1 || x == 2 ) return 0; if( g[x] != 0 ) return g[x]; return g[x] = f(x/2) + f( x/2 + (x&1)) + (x&1); } void solve(){ int n = read(); cout << f(n) << "\n"; } int32_t main() { for( int t = read() ; t ; t -- ) solve(); return 0; }

8|0数字三角形


#include<bits/stdc++.h> using namespace std; int32_t main() { int n; cin >> n; for( int i = 1 , t = 1 ; i <= n ; i ++ ){ for( int j = 1 ; j <= i ; j ++ , t ++ ) cout << setw(4) << t; cout << "\n"; } return 0; }

9|0[NOIP2005]采药


https://ac.nowcoder.com/acm/contest/24213/1018

#include <bits/stdc++.h> using namespace std; int main(){ int n, m; cin >> n >> m; vector<int> f( n+1 , INT_MIN ); f[0] = 0; for( int v , w ; m ; m -- ){ cin >> v >> w; for( int i = n ; i >= v ; i -- ) f[i] = max( f[i] , f[i-v] + w); } cout << *max_element(f.begin(), f.end()); return 0; }

10|0[NOIP2004]合唱队形


求两边最长上升子序列,枚举中间点

#include<bits/stdc++.h> using namespace std; #define int long long int read() { int x = 0, f = 1, ch = getchar(); while ((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } int32_t main() { int n = read(); vector<int> a(n+1) , f(n+1 , 1 ) , g(n+1 , 1 ); for( int i = 1 ; i <= n ; i ++ ) a[i] = read(); for( int i = 1 ; i <= n ; i ++ ) for( int j = 1 ; j < i ; j ++ ) if( a[j] < a[i] ) f[i] = max( f[i] , f[j] + 1 ); for( int i = n ; i >= 1 ; i -- ) for( int j = n ; j > i ; j -- ) if( a[j] < a[i] ) g[i] = max( g[i] , g[j] + 1 ); int res = INT_MIN; for( int i = 1 ; i <= n ; i ++ ) res = max( res , f[i] + g[i] - 1); cout << n - res << "\n"; return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/17334378.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示