【解题报告】13级个人结业赛(二) ——动(dou)态(bu)规(hui)划(zuo)专场
额。果然是动(dou)态(bu)规(hui)划(zuo)专场。。。
A: 翻倍序列
dp[i][j]表示第i个位置是j的情况的个数
那么dp[i][j]=∑dp[i-1][k] (j%k==0)
初始状态下dp[0][j]=1。(1<=j<=n)
最后要求的答案是∑dp[n-1][i] (1<=i<=n)
可以先预处理好所有答案,然后询问的时候直接求和输出。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define FOR(i,n) for(i=0;i<(n);i++)
#define CLR(a) memset(a,0,sizeof(a))
#define CIN(a) scanf("%d",&a)
typedef long long ll;
using namespace std;
int dp[][];
const int MOD=;
int main()
{
int n,k,i,j,kk;
n=,k=;
for(j=;j<=n;j++) dp[][j]=;
for(i=;i<k-;i++){
for(j=;j<=n;j++){
for(kk=j;kk<=n;kk+=j){
dp[i+][kk]=(dp[i+][kk]+dp[i][j])%MOD;
}
}
}
while(scanf("%d%d",&n,&k)!=EOF) {
int ans=;
for(j=;j<=n;j++){
ans=(ans+dp[k-][j])%MOD;
}
printf("%d\n",ans);
}
return ;
}
B: 汉诺塔
dp[k][i][j]表示把k个盘子从i移动到j所需要的最小花费。
首先z=3-i-j,表示除了i和j的另一个柱子
那么移动的时候有2种情况:
1.先把k-1个从i移动到z,然后把最大的那个从i移动到j,最后把z-1个从k移动到j
也就是dp[k][i][j]=dp[k-1][i][z]+cost[i][j]+dp[k-1][z][j]
2.先把k-1个从i移动到j,然后把最大的那个从i移动到z,之后把k-1个从j移动回i,再把最大的从z移动到j,最后k-1个从i移动到j
也就是dp[k][i][j]=dp[k-1][i][j]+cost[i][z]+dp[k-1][j][i]+cost[z][j]+dp[k-1][i][j]
然后两者取较小值。
最后要注意的是dp[0][i][j]=min{cost[i][j] , cost[i][z]+cost[z][j]}
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define FOR(i,n) for(i=0;i<(n);i++)
#define CLR(a) memset(a,0,sizeof(a))
#define CIN(a) scanf("%d",&a)
typedef long long ll;
using namespace std;
int cost[][];
ll DP[][][];
ll dfs(int n,int i,int j){
//printf("%d %d %d\n",n,i,j);
int k=-i-j;
if(n==) return min(cost[i][j],cost[i][k]+cost[k][j]);
if(DP[n][i][j]!=-){
return DP[n][i][j];
}
ll ans1=;
ans1=dfs(n-,i,k);
ans1+=cost[i][j];
ans1+=dfs(n-,k,j); ll ans2=;
ans2=dfs(n-,i,j);
ans2+=cost[i][k];
ans2+=dfs(n-,j,i);
ans2+=cost[k][j];
ans2+=dfs(n-,i,j); return DP[n][i][j]=min(ans1,ans2);
}
int main()
{
int n;
while(scanf("%d%d%d",&cost[][],&cost[][],&cost[][])!=EOF)
{
memset(DP,-,sizeof(DP));
scanf("%d%d%d",&cost[][],&cost[][],&cost[][]);
scanf("%d%d%d",&cost[][],&cost[][],&cost[][]);
scanf("%d",&n);
printf("%lld\n",dfs(n,,));
}
return ;
}
C: 红黑树
dp[i][0]表示有i个节点的树,如果根节点是黑色,有几种构造。
dp[i][1]表示有i个节点的树,如果根节点是红色,有几种构造。
根据题意可知,最后要求的就是dp[n][0]的值(根节点必须是是黑色)
dp[i][0]= dp[i/2+i%2][0]*dp[i/2][0]
+dp[i/2+i%2][0]*dp[i/2][1]
+dp[i/2+i%2][1]*dp[i/2][0]
+dp[i/2+i%2][1]*dp[i/2][1]
dp[i][1]= dp[i/2+i%2][0]*dp[i/2][0]
dp[1][0]=1
dp[1][1]=0 (叶子节点不能是红色)
dp[2][1]=dp[2][0]=1
然后递推就行了。。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define FOR(i,n) for(i=0;i<(n);i++)
#define CLR(a) memset(a,0,sizeof(a))
#define CIN(a) scanf("%d",&a)
typedef long long ll;
using namespace std;
const ll MOD=;
ll DP[][];
ll dfs(int x,int c)//x个节点,根节点颜色是c(0黑 1红)
{
//if(x<0) return 0;
if(x==&&c==) return ;//叶子节点不能是红色
if(x==) return ;//叶子节点是黑色
if(DP[x][c]!=) return DP[x][c];
ll ret=,l,r;
if((x-)%) l=(x-)/+;
else l=(x-)/;
r=(x-)/;
if(!c){//黑色
if(r!=){
ret=(ret+(dfs(l,)*dfs(r,))%MOD)%MOD;
ret=(ret+(dfs(l,)*dfs(r,))%MOD)%MOD;
ret=(ret+(dfs(l,)*dfs(r,))%MOD)%MOD;
ret=(ret+dfs(l,)*dfs(r,)%MOD)%MOD;
}else{ret=;}
}else{
if(r!=){
ret=(ret+dfs(l,)*dfs(r,)%MOD)%MOD;
}else{ret=;}
}
return DP[x][c]=ret;
}
int main()
{
int n;
memset(DP,,sizeof(DP));
while(scanf("%d",&n)!=EOF){
printf("%lld\n",dfs(n,));
}
return ;
}
D: 01序列
dp[i][0]表示前i个字符组成的的子序列中 以0为结尾的01序列
dp[i][1]表示前i个字符组成的的子序列中 以1为结尾的01序列
dp[i][0]=dp[i-1][1]+1 dp[i][1]=dp[i-1][1] (s[i]==0)
dp[i][1]=dp[i-1][0]+1 dp[i][0]=dp[i-1][0] (s[i]==1)
把全部加起来就是答案了。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define FOR(i,n) for(i=0;i<(n);i++)
#define CLR(a) memset(a,0,sizeof(a))
#define CIN(a) scanf("%d",&a)
typedef long long ll;
using namespace std;
int main()
{
int n,i;
int MOD=;
while(scanf("%d",&n)!=EOF){
ll ans=;
ll a0=,a1=;
for(i=;i<n;i++){
if(i%){
ans=(ans+(a0+))%MOD;
a1=(a1+a0+)%MOD;
}else{
ans=(ans+(a1+))%MOD;
a0=(a0+a1+)%MOD;
}
}
printf("%lld\n",ans);
}
return ;
}
E: 矩阵的最长不降子串
dp[i][j]表示以a[i][j]结尾的不递减子串最长的长度
那么dp[i][j]=max{
if(a[i][j]>=a[i-1][j]) dp[i-1][j]+1
if(a[i][j]>=a[i][j-1]) dp[i][j-1]+1
}
最后答案是最大的dp[i][j]
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define FOR(i,n) for(i=0;i<(n);i++)
#define CLR(a) memset(a,0,sizeof(a))
#define CIN(a) scanf("%d",&a)
typedef long long ll;
using namespace std;
int dp[][];
int a[][];
int n,m;
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF){
int ans=;
for(i=;i<n;i++){
for(j=;j<m;j++){
scanf("%d",&a[i][j]);
dp[i][j]=;
if(i!=&&a[i-][j]<=a[i][j]){
dp[i][j]=max(dp[i][j],dp[i-][j]+);
}
if(j!=&&a[i][j-]<=a[i][j]){
dp[i][j]=max(dp[i][j],dp[i][j-]+);
}
ans=max(ans,dp[i][j]);
}
}
printf("%d\n",ans);
}
return ;
}
【解题报告】13级个人结业赛(二) ——动(dou)态(bu)规(hui)划(zuo)专场的更多相关文章
- 2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告
2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- 2014 ACM/ICPC 鞍山赛区现场赛 D&I 解题报告
鞍山现场赛结束了呢-- 我们出的是D+E+I三道题-- 吾辈AC掉的是D和I两道,趁着还记得.先在这里写一写我写的两道水题D&I的解题报告吧^_^. D题的意思呢是说星云内有一堆排成一条直线的 ...
- 10.30 NFLS-NOIP模拟赛 解题报告
总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没 ...
- nowcoder(牛客网)OI测试赛2 解题报告
qwq听说是一场普及组难度的比赛,所以我就兴高采烈地过来了qwq 然后发现题目确实不难qwq.....但是因为蒟蒻我太蒻了,考的还是很差啦qwq orz那些AK的dalao们qwq 赛后闲来无事,弄一 ...
- 冲刺Noip2017模拟赛3 解题报告——五十岚芒果酱
题1 素数 [问题描述] 给定一个正整数N,询问1到N中有多少个素数. [输入格式]primenum.in 一个正整数N. [输出格式]primenum.out 一个数Ans,表示1到N中有多少个素 ...
- ZROIDay4-比赛解题报告
ZROIDay4-比赛解题报告 扯闲话 感觉这个出题人的题做起来全都没感觉啊,今天又凉了,T1完全不知道什么意思,T2只会暴力,T3现在还不懂什么意思,真的太菜了 A 题意半天没搞懂爆零GG了,讲了一 ...
- ZROIDay3-比赛解题报告
ZROIDay3-比赛解题报告 瞎扯 从今天开始考试有点不在状态,可能是因为不太适应题目的原因,T1已经接近了思想但是没有想到状态转移,T2思考方向错误,T3不会打LCT,还是太菜了 A 考场上想到要 ...
- 模拟赛T2 交换 解题报告
模拟赛T2 交换 解题报告 题目大意: 给定一个序列和若干个区间,每次从区间中选择两个数修改使字典序最小. \(n,m\) 同阶 \(10^6\) 2.1 算法 1 按照题意模拟,枚举交换位置并比较. ...
随机推荐
- LeetCode——Find Largest Value in Each Tree Row
Question You need to find the largest value in each row of a binary tree. Example: Input: 1 / \ 3 2 ...
- The SO_REUSEPORT socket option
One of the features merged in the 3.9 development cycle was TCP and UDP support for the SO_REUSEPORT ...
- 纯js提交get和post请求
get function get(URL, PARAMS) { var temp = document.createElement("form"); temp.method = & ...
- Markdown锚点使用
为了使得博客看起来更加美观,我更倾向于使用索引,但是如何在Markdown使用索引跳到指定位置呢?以下是使用方法: 具体应用场景: (1)文献列表中链接--可以通过锚实现页面内的链接:引用文献中可能需 ...
- Memcached stats sizes 命令
Memcached stats sizes 命令用于显示所有item的大小和个数. 该信息返回两列,第一列是 item 的大小,第二列是 item 的个数. 语法: stats sizes 命令的基本 ...
- 做文件上传下载时报这个错com.alibaba.fastjson.JSONException: illegal identifier : \
::-exec-] DEBUG c.i.e.m.I.insertDataEmebeding - <== Updates: ::-exec-] ERROR c.i.e.c.CaseArchiveC ...
- item2 - MAC 下最好的终端工具
1.http://www.iterm2.com/downloads.html (下载地址)
- Project facet Java 1.8 is not supported by target runtime Apache Tomcat v7.0.
找到项目下的“.settings”
- SPOJ 694 && SPOJ 705 (不重复子串个数:后缀数组)
题意 给定一个字符串,求它的所有不重复子串的个数 思路 一个字符串的子串都必然是它的某个后缀的前缀.对于每一个sa[i]后缀,它的起始位置sa[i],那么它最多能得到该后缀长度个子串(n-sa[i]个 ...
- 这可能是最详细的 iOS 学习入门指南(含书目/文档/学习资料)
1 零基础小白如何进行 iOS 系统学习 首先,学习目标要明确: 其次,有了目标,要培养兴趣,经常给自己一些正面的反馈,比如对自己的进步进行鼓励,在前期小步快走: 再次,学技术最重要的一点就是多动手. ...