一些关于DP的知识
1 /*在数轴上有0-N的位置 2 从0出发每次可以向右走 3 2 4 23 5 233步*/ 6 7 // 1 总共的方案数 8 9 f[i]=f[i-2]+f[i-23]+f[i-233]; 10 11 f[0]=1; 12 for (int a=1;a<=n;a++) 13 { 14 if (a>=2) f[a]+=f[a-2]; 15 if (a>=23) f[a]+=f[a-23]; 16 if (a>=233) f[a]+=f[a-233]; 17 } 18 printf("%d\n",f[n]); 19 20 // 2 考虑恰好t次到达时 21 //dp 题 可以考虑 每多一个条件 数组就多一维;所以,开二维数组 22 //f[i][j] 表示 用 j 步走了i种方案 23 24 f[i][j]=f[i-2][j-1]+f[i-23][j-1]+f[i-233][j-1]; 25 26 f[0][0]=1; 27 for (int a=1;a<=n;a++) 28 for (int b=1;b<=t;b++) 29 { 30 if (a>=2) f[a][b]+=f[a-2][b-1]; 31 if (a>=23) f[a][b]+=f[a-23][b-1]; 32 if (a>=233) f[a][b]+=f[a-233][b-1]; 33 } 34 printf("%d\n",f[n][t]); 35 int ans=0; 36 for (int a=0;a<=t;a++) 37 ans+=f[n][a]; 38 printf("%d\n",ans); 39 40 // 3 考虑小于t次 41 //将 42 f[n][1]+f[n][2]+....f[n][t]; 43 44 //考虑最多走r步233 45 //so 要再加一维,变成三维数组 46 //f[i][j][k] 表示走到 i点,公用j步,走233用了k步 47 48 f[i][j][k]=f[i-2][j-1][k]+ f[i-23][j-1][k]+ f[i-233][j-1][k-1]; 49 /* 50 (N,M)的方格图 51 从(0,0)开始 52 只能朝右或上走 53 问走到(N,M)的方案数*/ 54 55 //将每个点的左边点和下边点相加 56 57 f[n][m]=f[n-1][m]+f[n][m-1]; 58 59 //考虑有k个点(x,y)不能走 60 //定义布尔数组记录每个不能坐的点 61 每次设f[x][y]=0,并加以判断; 62 63 //2.考虑每个坑只能掉一次: 64 if(不是坑) 65 66 F[i][j][k]=f[i-1][j][k]+f[i][j-1][k]; 67 68 else if(是坑) 69 70 F[i][j][1]=f[i-1][j][0]-f[i][j-1][0]; 71 72 73 #include<iostream> 74 using namespace std; 75 int main() 76 { 77 int n,i,j,a[101][101]; 78 cin>>n; 79 for (i=1; i<=n; i++) 80 for (j=1; j<=i; j++) 81 cin>>a[i][j]; //输入数字三角形的值 82 for (i=n-1; i>=1; i--) 83 for (j=1; j<=i; j++) 84 { 85 if (a[i+1][j]>=a[i+1][j+1]) 86 a[i][j]+=a[i+1][j]; //路径选择 87 else a[i][j]+=a[i+1][j+1]; 88 } 89 cout<<a[1][1]<<endl; 90 } 91 //************矩阵乘法************* 92 93 //性质 94 95 /*乘法结合律: (AB)C=A(BC).[2] 96 乘法左分配律:(A+B)C=AC+BC[2] 97 乘法右分配律:C(A+B)=CA+CB[2] 98 对数乘的结合性k(AB)=(kA)B=A(kB). 99 转置 (AB)T=BTAT. 100 矩阵乘法一般不满足交换律*/ 101 102 103 104 105 // M1(n*m)*M2(m*k)=M2(n*k) 106 107 //M1的每一行 (i) 乘以M2的每一列 (j) 所得到的 对应元素相乘的积 再相加求和 得到 M3的(i,j)处的数值 108 109 //已知 M1 , M2 , 求 M3 110 //代码实现: 111 112 for (int a=1;a<=n;a++) 113 for (int b=1;b<=m;b++) 114 for (int c=1;c<=k;c++) 115 m3[a][c]+=m1[a][b]*m2[b][c];//M1 的行 && M2 的列 组成 M3 的 坐标 ,很好理解 116 117 //a 表示 M1 的行 && M2 的行,b表示 M1 的列 ,c表示 M2 的列 ; 118 //所以 M3 为 a 行,c 列 数组 119 120 121 int fib(int a) 122 { 123 if (!a) return 0; 124 if (a==1) return 1; 125 if (g[a]) return f[a]; 126 g[a]=true; 127 f[a]=fib(a-1)+fib(a-2); 128 return f[a]; 129 } 130 数字三角形问题,使得答案对p取模最大? 131 132 133 F[i][j][k] 表示走到第i行第j列 使得答案模p是否可行 134 135 F[i][j][k]=f[i+1][j][k-v[i][j]] 136 Or 137 F[i+1][j+1][k-v[i][j]] 138 **********代码: 139 140 for (int a=1;a<=n;a++) 141 f[n][a][v[n][a]%p]=true; 142 for (int a=n-1;a>=1;a--) 143 for (int b=1;b<=a;b++) 144 for (int c=0;c<p;c++) 145 f[a][b][c]= 146 f[a+1][b][(c-v[a][b]+p)%p] || 147 f[a+1][b+1][(c-v[a][b]+p)%p]; 148 int ans; 149 for (int a=p-1;a>=0;a--) 150 if (f[1][1][a]) 151 { 152 ans=a; 153 break; 154 } 155 156 //***********区间DP******** 157 158 /*合并石子 159 160 每次选择相邻两堆 161 162 代价为两堆石子和 163 164 问最小总代价 165 166 167 (第一层for循环一定要正着写) 168 169 因为后一层循环需要前一层循环的数据 */ 170 171 F[l][r]=min(f[l][k]+f[k+1][r]+sum[l][r]) 172 173 174 /*矩阵乘法 175 自定义顺序 176 使得运算次数最少*/ 177 178 //F[i][j] 表示搞定[I,j]的最小代价 179 F[i][j] = min(f[i][k]+f[k][j+1]+cost(I,k,j))
DP 骗分,All骗分 180 /*1.样例,( 现在来说应该不行了 ) 181 182 2.搜索,( 万分爆力的枚举 ) 183 184 3.大小->贪心:( 找个尽可能科学的方法说服自己,得部分 分 ) 185 《1》每次选代价最小的两个矩阵 186 《2》 每次选最大。。。。 187 《3》手动找规律。。。。。。。 188 189 4.随机化( 听天由命吧 ) 190 Int t=clock(); 191 While(clock()-t>950) 192 { 193 Do something;}*/
相信你会收获许多******
想了解关于“数据结构”的知识,请于本园搜索 “数据结构” ;