hdu 4293
地址:http://acm.hdu.edu.cn/showproblem.php?pid=4293
题意:一行人行走,分成很多组,每个人要说出他前面和后面分别有多少个人,他自己团队的人可以忽略,问最多有多少人说真话了。
mark:学习了大牛的思路,真是没话说。。想不到……大牛的思路是dp[i][j]代表前i个人并且i+1到j个人是一个团队的时候,最多有多少人说真话。
http://blog.csdn.net/taozifish/article/details/7985044
我在研究了他的代码之后,发现代码可以优化,优化之后顿时有一种豁然开朗的感觉,我知道为什么会这样想了。
dp[i]表示前i个人最多有多少人说真话,那么这一状态是无后效性的,现在要找最优子结构。
由于初始化的时候w[i][j]是记录的都说前面是i个人,后面是j个人的人的个数,那么dp[i]的前i个人就可以分隔成dp[j](1 <= j < i)+w[j][n-i](这就是一个典型的最优子结构,想通了也就做出来了。)
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <iostream> #include <algorithm> #include <map> #define LL long long using namespace std; const int N = 510; int n; int w[N][N],dp[N]; int max(int a, int b) {return a > b ? a : b;} int main() { int i,j,k; while(~scanf("%d", &n)) { memset(w, 0, sizeof(w)); memset(dp, 0, sizeof(dp)); for(i = 1; i <= n; i++) { scanf("%d%d", &j, &k); if(j+k < n) { w[j][k]++; if(w[j][k] > n-j-k) w[j][k] = n-j-k; } } for(j = 1; j <= n; j++) for(i = 0; i < j; i++) dp[j] = max(dp[i]+w[i][n-j], dp[j]); printf("%d\n", dp[n]); } return 0; }