HDU5000 (DP + 规律)
题意:举例子好说点,告诉你4个数字,8,6,4,2四个数字,组成一个四位数,如果两个数字分别是1111,2222,则2222会吧1111杀掉,就是组成的四位数不能每一位都小于或等于一个数,然后让你求出最大能够存活的数目。
分析:场上的时候自己一直在找规律,推公式,以为是四个数字递增递减交替的规律,没想到是和是一定的规律,即num/2,和一定了那就是DP了;
PS: 我其实对DP是很发怵的,但是我觉得最起码还是要DP入门!感觉找到规律后这个题目就挺简单的!本来我对DP有个固定看法,那就是贪心能做的题,DP都能做,但是DP能做的,
贪心有可能做不了,也感觉DP,贪心,推公式,三者联系很密切,有时候找不到规律或者贪不下去就找DP。
1 #include <cstdio> 2 #include <iostream> 3 #include <sstream> 4 #include <cmath> 5 #include <cstring> 6 #include <cstdlib> 7 #include <string> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <stack> 13 #include <algorithm> 14 using namespace std; 15 #define ll long long 16 #define _cle(m, a) memset(m, a, sizeof(m)) 17 #define repu(i, a, b) for(int i = a; i < b; i++) 18 #define repd(i, a, b) for(int i = b; i >= a; i--) 19 #define sfi(n) scanf("%d", &n) 20 #define sfl(n) scanf("%lld", &n) 21 #define pfi(n) printf("%d\n", n) 22 #define pfl(n) printf("%lld\n", n) 23 #define N 6005 24 #define MOD 1000000007 25 int t[N],d[N][N]; 26 27 int main() 28 { 29 int n,T; 30 scanf("%d",&T); 31 while(T--) 32 { 33 scanf("%d",&n); 34 memset(t,0,sizeof(t)); 35 int sum = 0; 36 repu(i,0,n) 37 { 38 scanf("%d",&t[i+1]); 39 sum += t[i+1]; 40 } 41 sum /= 2; 42 repu(i,0,2001)///初始化 43 repu(j,0,2001) 44 d[i][j] = 0; 45 46 repu(i,0,t[1]+1)///当只有一个人的时候,和是i,只有一种方案 47 d[1][i] = 1; 48 49 repu(i,2,1+n)///属性数目 50 { 51 repu(j,0,sum+1)///和 52 { 53 repu(k,0,t[i]+1) 54 { 55 if(j < k) 56 break; 57 d[i][j] = (d[i-1][j-k] + d[i][j]) % MOD; 58 ///只需要在前一个的基础上加k,因为和是一定的 59 ///举例说明,t分别是8 6 4 2 60 ///目前d[3][10],k等于4,则等于 += d[2][6],则在第四位上+4 61 ///而且完全可以在第四位上加到满为止 62 } 63 } 64 } 65 printf("%d\n",d[n][sum]); 66 } 67 return 0; 68 }
看别人代码能明白啥意思,自己写就不知道该怎么分状态。。。
人生就像心电图,想要一帆风顺,除非game-over