转化真的是太神了,看了一下题解的提示,唉,真的是一个考验思维的题目。
题目大意:n个人一起走,可以分成很多组,每个人说一句话,前面有几个人,后面有有几个人,最多有多少个人说真话。
网赛的时候真心一点想法都没有啊,不知从何下手。。。看了一下题解的提示,这个问题只要转化一下,就是自己可以解决的问题了。每个人说的话,转化为一个区间,只需求最大不重叠区间的数目就可以了,这样就是以前做过的,排序后的线性的DP问题。敲的出来WA1次了,好在想了想有没有漏的情况,检查了出来,注意一下区间相同的时候的情况搞了个标记数组乱搞一下,2Y。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 struct node 7 { 8 int str; 9 int end; 10 }p[501]; 11 int cmp(const node &a,const node &b) 12 { 13 if(a.str < b.str) 14 return 1; 15 else if(a.str > b.str) 16 return 0; 17 else if(a.end < b.end) 18 return 1; 19 else 20 return 0; 21 } 22 int dp[501],o[501]; 23 int main() 24 { 25 int i,j,k,n,a,b,num,ret; 26 while(scanf("%d\n",&n)!=EOF) 27 { 28 memset(dp,0,sizeof(dp)); 29 memset(o,0,sizeof(o)); 30 num = 0; 31 for(i = 1;i <= n;i ++) 32 { 33 scanf("%d%d",&a,&b); 34 if(a+1 <= n-b) 35 { 36 p[num].str = a+1; 37 p[num].end = n-b; 38 num ++; 39 } 40 } 41 sort(p,p+num,cmp); 42 dp[0] = 1; 43 for(i = 1;i < num;i ++) 44 { 45 ret = 0; 46 for(j = 0;j < i;j ++) 47 { 48 if(p[i].str > p[j].end) 49 { 50 if(ret < dp[j]) 51 { 52 ret = dp[j]; 53 k = j; 54 } 55 } 56 if(p[i].str == p[j].str&&p[i].end == p[j].end) 57 { 58 if(ret < dp[j]&&o[j] < p[i].end - p[i].str) 59 { 60 ret = dp[j]; 61 k = j; 62 } 63 } 64 } 65 if(p[i].str == p[k].str&&p[i].end == p[k].end) 66 { 67 o[i] = o[k] + 1; 68 } 69 dp[i] = ret+1; 70 } 71 ret = 0; 72 for(i = 0;i < num;i ++) 73 { 74 if(ret < dp[i]) 75 { 76 ret = dp[i]; 77 } 78 } 79 printf("%d\n",ret); 80 } 81 return 0; 82 }