摘要:/*经典模型:最长公共子序列+字符串处理 */View Code 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define max( a, b ) ((a)>(b)?(a):(b)) 6 7 char LeftOS[ 1001 ][ 12 ]; 8 char RightOS[ 1001 ][ 12 ]; 9 int LeftID[ 1001 ];10 int LeftV[ 1001 ];11 int RightID[ 1001 ];12 int RightV
阅读全文
摘要:/*经典模型:完全背包本问题有两种考虑思路:1.一维多重背包,每个阶段由一个状态改为四个状态,容易想到跟阶段间的转移方程。2.二维完全背包,同一维一样,转移方程:F(i,j,k) = opt{ F(i-V(i),j-C(i),k-1),F(i,j,k-1) } (k为阶段)*/View Code 1 #include <stdio.h> 2 #include <string.h> 3 4 int F[ 5 ][ 32770 ]; 5 6 int main() 7 { 8 int i,j,k; 9 memset( F, 0, sizeof( F ) );10 F[ ...
阅读全文
摘要:/*和前面的几道题目很像,也是基于前后大小关系的字符串DP状态为:F(l,s) 代表长度为l的起始为s的元素的个数。按长度为阶段,转移方程为:F(l,s) = sum{ F(l-1,t) } ( s < t )然后利用递推关系计算出所有长度为l的小于这个串的个数在加上长度小于l的串的个数即可。╮(╯▽╰)╭,刚开始状态设成:长度为l的结束为e的元素的个数,不好推,纠结了好久。。。*/View Code 1 #include <stdio.h> 2 #include <string.h> 3 4 int Count[ 6 ][ 27 ]; 5 char Data[
阅读全文
摘要:/*不错的题目:如果没有首尾相连的话,这个题目就很简单了: 动态方程:F( n ) = max( F[ n-1 ], F[ n-2 ] +D[ n ] ) 题目分析: 现在告诉我们首尾相连,为了无后效性,我们要把环拆开。 我们把起始时分为两种状况,取或不取,当取第一个元素时,我们DP到n-1位置;当不取第一个元素时,我们DP到n位置。 时间复杂性:O(n) */View Code 1 #include <stdio.h> 2 #include <string.h> 3 4 int D[ 1000002 ]; 5 int F[ 1000002 ]; 6 int G[ 10
阅读全文
摘要:/*概率计算:按时间为阶段,每个点由上一阶段周围的四个点来维护。注意事项:1.时间O(N^3*T),在问题的边缘时间,所以打表计算。 2.关于概率的求解,如果遇到就结束了,所以向后走就说明 之前没有碰到,所以不用前面的碰到的概率计算后面的值。 */View Code 1 #include <stdio.h> 2 #include <string.h> 3 4 double answ[ 51 ] = { 5 0.0000,0.6667,0.0000,0.4074,0.0000, 6 0.3361,0.0000,0.2928,0.0000,0.2629, 7 0.0000,
阅读全文
摘要:/* 经典模型:最大不下降子序列,将每个箱子旋转三次即可,用贪心可证,长边对齐原则 */View Code 1 #include <iostream> 2 #include <cstdlib> 3 4 using namespace std; 5 6 int P[ 6 ][ 3 ] = { 7 0,1,2,0,2,1, 8 1,0,2,1,2,0, 9 2,0,1,2,1,0};10 11 struct node{12 int D[ 3 ];13 }N[ 31 ],S[ 185 ];14 15 int DP[ 185 ];16 17 int cmp( const voi
阅读全文
摘要:/* 这道题算不上难题,不过算得上的麻烦题了。设状态 T[ i ][ j ] 为程序1执行i条指令,程序2执行j条指令后的变量平均值,P1为程序1指令i的概率,P2为程序2指令j的概率则容易推出,T[ i ][ j ] = (T[ i-1 ][ j ]*P1+T[ i ][ j-1 ]*P2)/(P1+P2) 不过需要注意几点: 1.理解题意很重要,这个题很容易误解 。如果认为每种指令执行的情况是一样的话,就会求错方程:(设N[ i ][ j ]为状态T[ i ][ j ]数量 ) P1 = N[ i-1 ][ j ]/N[ i ][ j ]P2 = N[ i ][ j-1 ]/N[ i ][
阅读全文
摘要:/* 单调队列优化的最大上升子序列 O(NlogN)算法*/View Code 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 int data[ 40000 ]; 6 int Queu[ 40000 ]; 7 8 int Search( int h, int key ) 9 {10 if ( key <= Queu[ 0 ] ) return 0;11 int m,l = 0;12 while ( l < h ) {13 m = (h+l)>>
阅读全文
摘要:/*简单DP:裸的最大公共子序列 */View Code 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 5 using namespace std; 6 7 int CtoI( char ch ) 8 { 9 if ( ch >= 'a' && ch <= 'z' )10 return ch - 'a';11 else return ch - 'A' + 26;12 }13 14 i
阅读全文
摘要:/*动态三角形:每次DP时考虑的是两个子三角形的高度即可注意:三角形可以是倒置的。 */View Code 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <stdio.h> 5 6 using namespace std; 7 8 char Tri[ 101 ][ 201 ]; 9 short Val[ 101 ][ 201 ];10 11 int main()12 {13 int n,cases = 1;14 while ( scanf(&q
阅读全文
摘要:/*01背包:整数拆分问题 */View Code 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 5 using namespace std; 6 7 long long dp[ 501 ]; 8 9 int main()10 {11 memset( dp, 0, sizeof( dp ) );12 dp[ 0 ]= 1;13 for ( int i = 1 ; i <= 500 ; ++ i )14 for ( int j = 500 ; j >= i ; -
阅读全文
摘要:/*简单的树形DP:利用搜索正向求解。 0的孩子必须是1,1的孩子任意,取最小的。 */View Code 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define min(x,y) ((x)<(y)?(x):(y)) 6 7 typedef struct node 8 { 9 int Count;10 int Value;11 int Next[ 10 ];12 }node;13 node Node[ 1510 ];14 int Root;15 16 ty
阅读全文
摘要:/*简单的模拟:可以用栈,也可以用递归实现*/View Code 1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 struct node 7 { 8 int L,R; 9 long long V;10 }Matrix[ 27 ],Error;11 12 bool Flag;13 14 node Calculate( char* Data, int s, int e )15 {16 int count = 0;17 node Save[ 2 ];18 for ( int i =
阅读全文
摘要:/*经典模型:最长公共子序列 */View Code 1 #include <iostream> 2 #include <cstdlib> 3 4 using namespace std; 5 6 int Geno[ 210 ][ 210 ]; 7 int Matr[ 5 ][ 5 ] = { 8 { 5,-1,-2,-1,-3}, 9 {-1, 5,-3,-2,-4},10 {-2,-3, 5,-2,-2},11 {-1,-2,-2, 5,-1},12 {-3,-4,-2,-1, 0}};13 14 int V( char C )15 {16 switch( C )
阅读全文
摘要:/*背包变形:如果按照完全背包计算会有后效性,所以用01背包计算注意两点:1.数据的范围,因为要做差,所以数据要超过100 2.背包时物品的顺序,本题的解会受到顺序影响, 所以先对所有数据01背包,然后再次01背包。补充:忽然发现bfs是DP,按广度为阶段,并且每个值最求一次#24*/View Code 1 #include <stdio.h> 2 #include <iostream> 3 4 using namespace std; 5 6 int F[ 205 ]; 7 int C[ 7 ]; 8 9 int main()10 {11 int T;12 while
阅读全文
摘要:/*背包类似物:关键是阶段的划分,昨天阶段想错了,其实阶段很明显了,今天调了一段时间,发现数据看错了,╮(╯▽╰)╭按照题目给出的阶段DP。转移方程 : F(i,j) = min( F(i-F1,j)+T1, F( i-1,j )+T2, F(i+F2,j)+T3 ) */View Code 1 #include <iostream> 2 #include <cstdlib> 3 4 using namespace std; 5 6 int F[ 111 ][ 111 ]; 7 int T1[ 111 ]; 8 int T2[ 111 ]; 9 int T3[ 111
阅读全文
摘要:/* 简单的搜索,欧拉回路的判断*/View Code 1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 bool maps[ 11 ][ 11 ]; 7 bool used[ 11 ]; 8 9 bool dfs( int n, int s, int d )10 {11 if ( d == n ) return true;12 bool value = false;13 for ( int i = 1 ; i <= n ; ++ i )14 if ( !used[ i
阅读全文
摘要:/*简单的DP:区间动态规划,对于一个m*n的蛋糕只有横竖两类切法 f( m, n ) = min{ f( m, i ) + f( m, n-i ), f( j, n ) + f( m-j, n ) } */View Code 1 #include <stdio.h> 2 3 short F[ 201 ][ 201 ]; 4 5 int main() 6 { 7 for ( int i = 0 ; i <= 200 ; ++ i ) 8 for ( int j = 0 ; j <= 200 ; ++ j ) 9 F[ i ][ j ]= i*j;10 11 for (
阅读全文
摘要:/*分析:三角N皇后问题,找规律题目,按照题目的输出,可以看出构造法则,先填奇数,后填偶数。下面我们只要证明这种构造的存在性即可。解法:先给出集体构造方法,从(1,n-f(n)+1) 开始填充奇数点,填充所有的(1+2k,n-f(n)+1+k){其中f(n)就是最大填充数,1+2k<=n-f(n)+1+k} 之后开始从(2,n-f(n)+1+k+1)开始填充偶数点,由于奇数点只能攻击奇数点,偶数点只能攻击偶数点,所以只要保证每行一个皇后就可以了。 证明: 我们只需要证明从第n-f(n)+1行开始,每行都可以放一个皇后就可以了。 首先,按照上面的构造可知,如此构造,皇后是不可以互相攻击的。
阅读全文
摘要:/*简单DP:分成奇偶两种状况考虑奇数情况:每个面的光线等于上次的本平面以上的点的反射偶数情况:每个面的光线等于上次的本平面以下的点的反射 */View Code 1 #include <stdio.h> 2 #include <string.h> 3 4 long long F[ 61 ][ 4 ]; 5 6 int main() 7 { 8 int i,j,k,n; 9 memset( F, 0L, sizeof( F ) );10 F[ 0 ][ 0 ] = 1L;11 12 for ( i = 1 ; i <= 60 ; ++ i )13 for ( j
阅读全文