【解题报告】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 按照题意模拟,枚举交换位置并比较. ...
 
随机推荐
- springBoot的文件上传功能
			
知识点: 后台:将上传的图片写入指定服务器路径,保存起来,返回上传后的图片路径(在springBoot中,参考博客:http://blog.csdn.net/change_on/article/det ...
 - 数据库还原,System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权。 (Microsoft.SqlServer.SmoExtended)
			
数据库还原问题: System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权. (Microsoft.SqlServer.SmoExtende ...
 - spring 或 springboot统一异常处理
			
spring 或 springboot统一异常处理https://blog.csdn.net/xzmeasy/article/details/76150370 一,本文介绍spring MVC的自定义 ...
 - C#  SQLite写入和读取DateTime类型
			
很简单 1.不要相信网上大部分人说的话,比如存到int里 (ps:版本差距知道吗?) 2.nuget包下载最新版的sqlite 3.SQLite支持DateTime类型(图形化工具不会给提示无视它), ...
 - C++(三十) — this 指针
			
1.如何区分多个对象调用同一个类函数? 类外部访问类成员,必须用对象来调用.一个类的所有对象在调用的成员函数,都执行同一段代码,那成员函数如何区分属于哪个对象呢? 在对象调用成员函数时,除接收实参外, ...
 - centos7 rabbitmq 安装
			
http://www.rabbitmq.com/install-rpm.html Overview rabbitmq-server is included in Fedora. However, th ...
 - MySQL相关问题总结
			
希望此贴能够将MySQL安装周围的问题总结清楚,也免得自己再遇到问题时而不知所措.本帖中所有关于MySQL的问题均涉及到两个平台:Ubuntu 和 Windows(本人没有Mac) 问题1:MySQL ...
 - jersey实现跨服务器上传
			
1.导入跨服务器上传文件jar文件 <dependency> <groupId>commons-io</groupId> <artifactId>com ...
 - Java复习4.数组初始化.
			
Java复习4.Java中的数组声明方式 20131004 1.数组声明和初始化, 数组元素和变量一样,可以在定义的时候i进行初始化.数组元素的初始化工作实在编译阶段完成的,可以减少运行时间. 在初 ...
 - C++进阶3.字节对齐 联合
			
C++进阶3.字节对齐 联合 20131011 多益和金山笔试 知识漏洞 20131011 前言: 今天下午是多益网络的笔试,整体感觉还好,但是找到很多的知识漏洞.一直笔试到6:00,然后紧张的从会生 ...