动态规划----颜料涂墙问题

来源:互联网 发布:淘宝好还是天猫好 编辑:程序博客网 时间:2024/05/01 17:32

问题描述:


有一面长度为n(n<=10000)的墙,如果要将每单位长度的墙涂上红、绿、篮其中的一种颜色,而且红色墙右边不能紧邻绿色的墙,绿色的墙右边不能紧邻蓝色的墙,请问有几种涂色的方法?




0代表红色,1代表绿色,2代表蓝色

初始值F(1, 0) = F(1, 1) = F(1, 2) = 1;

状态转移方程:

for(n>1)

F(n, 0) = F(n-1, 0)+F(n-1, 1)+F(n-1, 2)

F(n, 1) = F(n-1, 1)+F(n-1, 2)

F(n, 0) = F(n-1, 0)+F(n-1, 2)


下边两种代发原理是相同的,一种采用无记录的方式,另外采用一种有记录的方式:


方法一:无记录

#include<iostream>#include<algorithm>#include<ctime>using namespace std;long long f(int n, int c, long long *p){if (n == 1 && c == 0)return 1;if (n == 1 && c == 1)return 1;if (n == 1 && c == 2)return 1;if (c == 0) p[n] = f(n - 1, 0, p) + f(n - 1, 1, p) + f(n - 1, 2, p);//如果结尾颜色为红色if (c == 1)p[n] = f(n - 1, 1, p) + f(n - 1, 2, p);//如果结尾颜色为绿色if (c == 2)p[n] = f(n - 1, 0, p) + f(n - 1, 2, p);////如果结尾颜色为蓝色return p[n];}int main(){int n;int c[] = { 0, 1, 2 };while (cin >> n){long long *p = new long long[n + 1];memset(p, -1, sizeof(long long)*(n + 1));time_t t1, t2;t1 = clock();int f1 = f(n, 0, p);int f2 = f(n, 1, p);int f3 = f(n, 2, p);t2 = clock();cout << f1 + f2 + f3 <<"\t耗时:"<<(double)(t2-t1)/CLOCKS_PER_SEC<< endl;}printf("%s  %s\n", __DATE__, __TIME__);system("pause");return 0;}


运行结果:
105842    耗时:015396655  耗时:0.047184983377 耗时:0.2181911584946        耗时:0.6262026931732        耗时:1.0762162608681        耗时:2.57522145547525       耗时:5.71123338356945       耗时:13.288^ZAug 25 2016  10:36:34请按任意键继续. . .

从运算结果我们可以看到,这种无记录的计算方式是非常耗时的!!

方法二:有记录

#include<iostream>#include<algorithm>#include<ctime>using namespace std;long long f(int n, int c, long long **p){if (p[n][c] != -1)return p[n][c];long long m;if (n > 1){if (c == 0)m = p[n][0] = f(n - 1, 0, p) + f(n - 1, 1, p) + f(n - 1, 2, p);//如果结尾颜色为红色if (c == 1)m = p[n][1] = f(n - 1, 1, p) + f(n - 1, 2, p);//如果结尾颜色为绿色if (c == 2)m = p[n][2] = f(n - 1, 0, p) + f(n - 1, 2, p);////如果结尾颜色为蓝色}return m;}int main(){int n;int c[] = { 0, 1, 2 };while (cin >> n){long long **p = NULL;p = (long long **)malloc((n+1) * sizeof(long long *));//申请一个动态的二维数组for (int i = 0; i < n+1; ++i)p[i] = (long long *)malloc(3*sizeof(long long));//定义行for (int i = 0; i < n+1; ++i){for (int j = 0; j < 3; ++j)p[i][j] = -1;}p[1][0] = 1;p[1][1] = 1;p[1][2] = 1;time_t t1, t2;t1 = clock();long long  f1 = f(n, 0, p);long long  f2 = f(n, 1, p);long long  f3 = f(n, 2, p);t2 = clock();cout << f1 + f2 + f3 << "\t共耗时:" << (double)(t2 - t1) / (CLOCKS_PER_SEC) << endl;for (int i = 0; i < n + 1; ++i)free(p[i]);free(p);}cout << __DATE__ << "  " << __TIME__ << endl;system("pause");return 0;}

运行结果:
105842    共耗时:015396655  共耗时:02026931732        共耗时:02162608681        共耗时:022145547525       共耗时:023338356945       共耗时:0251828587033      共耗时:030124155792775    共耗时:0358429820731201   共耗时:0^ZAug 25 2016  10:40:00请按任意键继续. . .

从结果中我们可以看到,这种方法的运行时间非常快!!!






0 0
原创粉丝点击