• acm-DP整理


      1 一、背包
      2 1.各种01背包
      3 void leastOne_Pack(int id, int num ) {//至少取一个;
      4     int i, j, c, v ;
      5     for(i = 1 ; i <= num ; i ++ )
      6     {
      7         scanf("%d %d", &c, &v) ;
      8         for(j = T ; j >= c ; j -- ) 
      9         {// 下面的顺序不能交换;
     10             if(f[id][j-c] != -1 ) f[id][j] = getMax(f[id][j], f[id][j-c] + v ) ;
     11             if(f[id-1][j-c] != -1 ) f[id][j] = getMax(f[id][j], f[id-1][j-c] + v ) ;
     12         }
     13     }
     14 }
     15 void mostOne_Pack(int id, int num ) { // 最多取一个;
     16     int i, j ;
     17     int c[N], v[N] ;
     18     for(i = 1 ; i <= num ; i ++ ) scanf("%d %d", &c[i], &v[i] ) ;
     19     for(i = 0 ; i <= T ; i ++ ) f[id][i] = f[id-1][i] ;
     20     for(i = 1 ; i <= num ; i ++ )
     21     {
     22         for(j = T ; j >= c[i] ; j --)
     23             if(j >= c[i] && f[id-1][j-c[i]] != -1 ) f[id][j] = getMax(f[id][j], f[id-1][j-c[i]] + v[i] ) ;
     24     } 
     25 }
     26 void common_Pack(int id, int num ){ // 一般的01背包;
     27     int i, j, c, v ;
     28     for(i = 0 ; i <= T ; i ++ ) f[id][i] = f[id-1][i] ;
     29     for(i = 1 ; i <= num ; i ++ )
     30     {
     31         scanf("%d %d", &c, &v) ;
     32         for(j = T ; j >= c ; j -- ) 
     33             if(f[id][j-c] != -1 ) f[id][j] = getMax(f[id][j], f[id][j-c] + v ) ;
     34     }
     35 }
     36 2.完全背包
     37 void Comlepte_Pack(){
     38   for(i = 0 ; i < n ; i ++ )
     39   {
     40               scanf("%d %d", &p, &w ) ;
     41               for(j = w ; j <= vol ; j ++ ) 
     42                   f[j] = f[j] < f[j-w] + p ? f[j] : f[j-w] + p ;
     43   }
     44 }
     45 3.依赖背包
     46 struct Goods{
     47     int c, v ;
     48 } g[61][61] ;
     49 void dependent_Pack(int vol, int gn ){
     50     int i, j, k, mc, mv, c, v ;
     51     for(j = 1, f[0] = 0 ; j <= vol ; j ++ ) f[j] = -1 ;
     52     for(i = 1 ; i <= gn ; i ++ )
     53     {
     54         if( !num[i]) continue ;
     55         mc = g[i][0].c ; mv = g[i][0].v*mc ;
     56         for(j = 1, h[0] = 0 ; j <= vol-mc ; j++ ) h[j] = -1 ;
     57         for(k = 1 ; k < num[i] ; k ++ )//10背包,相当于得到0 - vol-mc种物品;
     58         {
     59             c = g[i][k].c ; v = g[i][k].v*c ;
     60             for(j = vol-mc ; j >= c ; j -- )
     61                 if(h[j-c] != -1 ) h[j] = h[j] > h[j-c]+v ? h[j] : h[j-c]+v ;
     62         }
     63         for(j = vol ; j >= mc ; j -- )//对于1 - vol-mc种物品,至多选择一种;
     64         {
     65             for(k = 0 ; k <= j-mc ; k ++ )
     66             {
     67                 if(h[k] == -1 ) continue ;
     68                 c = k+mc ; v = h[k]+mv ;
     69                 if(j >= c && f[j-c] != -1 ) f[j] = f[j] > f[j-c]+v ? f[j] : f[j-c]+v ;
     70             }
     71         }
     72     }
     73 }
     74 二、极大化
     75 1.极大化算法一
     76 以障碍点经过的边作为矩形的左边界,一直向右边扫描
     77 struct Point{
     78     int x, y ;
     79 }p[MAXN] ;
     80 bool comp(Point a, Point b){
     81     if(a.x == b.x) return a.y < b.y ;
     82     else return a.x < b.x ;
     83 }
     84 int DP(){// h,d 表示扫描线的上下端点高度
     85     int i, j, h, d, s ;
     86     int ans = 0 ;
     87     for (i = 1; i <= n; i ++) //枚举障碍点
     88     {
     89         h = W ; d = 0 ; 
     90         for(j = i+1 ; j <= n && h > d ; j ++)
     91         {
     92             if(p[i].x == p[j].x || p[j].y > h || p[j].y < d) continue ; 
     93             // 扫描得到的矩形一定要经过i点
     94             s = (h-d)*(p[j].x-p[i].x) ;
     95             ans = ans > s ? ans : s ;
     96             if(p[j].y < h && p[j].y >= p[i].y) h = p[j].y ; 
     97             //保证向前扫描一定经过i点
     98             if(p[j].y > d && p[j].y <= p[i].y) d = p[j].y ;
     99         }
    100     }
    101     return ans ;
    102 }
    103 int solve(){
    104     int i, j, tx, ans = 0 ;
    105     while(~scanf("%d %d", &L, &W))
    106     {
    107         scanf("%d", &n) ; memset(pre, 0, sizeof(pre)) ;
    108         for(i = 1 ; i <= n ; i ++) 
    109         {
    110             scanf("%d %d", &p[i].x, &p[i].y) ; pre[p[i].y]  = 1 ;
    111         }
    112         for(tx = 0, i = 1 ; i <= W ; i ++)
    113         {
    114             tx ++ ;
    115             if(pre[i]) 
    116             {
    117                 ans = ans > tx ? ans : tx ;
    118                 tx = 0 ;
    119             }
    120         }
    121         ans = ans*L ;
    122         p[++n].x = 0 ; p[n].y = 0 ; p[++n].x = 0 ; p[n].y = W ;
    123         p[++n].x = L ; p[n].y = 0 ; p[++n].x = L ; p[n].y = W ;
    124         sort(p+1, p+1+n, comp) ;
    125         tx = DP() ; printf("%d
    ", ans > tx ? ans : tx) ;
    126     }
    127   }
    128 
    129 
    130 
    131 
    132 
    133 2.算法二
    134  a.悬线的定义:上端点是障碍点或者边界的线段 ;
    135  (1) h[i][j]表示以点(i,j)结束的悬线的最大长度;
    136  (2) l[i][j]表示悬线(i,j)左移量,r[i][j]表示其右移量;
    137  (3) ml[i][j]表示点(i,j)左边最近的障碍点位置,没有时为左边界。同理……
    138  b.dp方程:
    139  (1) 如果点(i-1,j)为障碍点或边界(i=0):
    140      h[i][j] = 1,l[i][j] = L(大矩形长度),r[i][j] = 0141  (2) 如果点(i-1,j)不为障碍点:
    142      h[i][j]=h[i-1][j]+1, 
    143      l[i][j]=max(l[i-1][j],ml[i][j]), 
    144      r[i][j]=min(r[i-1][j],mr[i][j]).
    145 description :取最大周长矩形,该矩形要么由一种颜色覆盖,要么由两种颜色交叉覆盖。
    146 int h[3][MAXN][MAXN], l[3][MAXN][MAXN], r[3][MAXN][MAXN] ;
    147 int mr[3][MAXN][MAXN], ml[3][MAXN][MAXN] ; 
    148 //[i][j] 左右边最近的异色点,没有异色点为边界位置
    149 int map[MAXN][MAXN] ;
    150 void getTable(){//初始化数组
    151     int i, j ;
    152     for(i = 1 ; i <= n ; i ++)
    153     {
    154         map[i][0] = map[i][1] ; map[i][m+1] = map[i][m] ;
    155         ml[0][i][0] = 0 ; mr[0][i][m+1] = m+1 ;
    156         for(j = 1 ; j <= m ; j ++)
    157         {
    158             ml[1][i][j] = ml[0][i][j] = 
    159             (map[i][j]==map[i][j-1]) ? ml[0][i][j-1] : j-1 ;
    160             ml[2][i][j] = 
    161             (map[i][j]^map[i][j-1]) ? ml[2][i][j-1] : j-1 ;
    162         }
    163         for(j = m ; j ; j --)
    164         {
    165             mr[1][i][j] = mr[0][i][j] =
    166             (map[i][j]==map[i][j+1]) ? mr[0][i][j+1] : j+1 ;
    167             mr[2][i][j] = 
    168              (map[i][j]^map[i][j+1]) ? mr[2][i][j+1] : j+1 ;
    169         }
    170     }
    171 }
    172 int DP(){
    173     int i, j, k, ans = 0 ;
    174     for (i = 1 ; i <= n ; i ++)
    175         for (j = 1 ; j <= m ; j ++)
    176         {
    177             for(k = 0 ; k < 3 ; k ++)
    178             {
    179                 if(k < 2 && (map[i][j] != k)) continue ;
    180                 bool v = map[i][j]^map[i-1][j] ;
    181                 if(i == 1 || ((2-k) && v) || (!(2-k) && !v) ) //特判
    182                 {
    183                     h[k][i][j] = 1 ;
    184                     l[k][i][j] = ml[k][i][j] ;
    185                     r[k][i][j] = mr[k][i][j] ;
    186                 }
    187                 else                {
    188                     h[k][i][j] = h[k][i-1][j]+1 ;
    189                     l[k][i][j] = max(l[k][i-1][j], ml[k][i][j]) ;
    190                     r[k][i][j] = min(r[k][i-1][j], mr[k][i][j]) ;
    191                 }
    192                 ans = max(ans, 2*(r[k][i][j]-l[k][i][j]-1+h[k][i][j])) ;
    193             }
    194         }
    195     return ans ;
    196 }
    197 int solve(){
    198         getTable() ; printf("Case #%d: %d
    ", cas ++, DP()) ;
    199   }
    200 三、分数规划
    201 1.二分法
    202 double DP(double f){
    203     int i ;
    204     double ans ;
    205     for(i = 1 ; i <= n ; i ++) d[i] = 1.0*a[i] - b[i]*f;
    206     sum[0] = 0.0 ;
    207     for(i = 1 ; i <= n ; i ++) sum[i] = sum[i-1] + d[i] ;
    208     ans = sum[k] ; dp[k] = sum[k] ;
    209     for(i = k+1 ; i <= n ; i ++)
    210     {
    211         dp[i] = max(sum[i]-sum[i-k], dp[i-1]+d[i]) ;
    212         ans = max(ans, dp[i]) ;
    213     }
    214     return ans ;
    215 }
    216 double binary(double l, double r){
    217     double mid ;
    218     while(r-l > EPS)
    219     {
    220         mid = (l+r)/2.0 ;
    221         if(DP(mid) > EPS) l = mid+EPS ;
    222         else r = mid ;
    223     }
    224     return l ;
    225 }
    226 2.牛顿逼近法
    227 void build(double s){
    228     int i, j ;
    229     for(i = 1 ; i <= n ; i ++)
    230     for(j = 1 ; j <= n ; j ++)
    231     {
    232         map[i][j].d = map[i][j].l - s*map[i][j].c ;
    233     }
    234 }
    235 double solve(){
    236     int i ;
    237     double s, ans = 1.0 ;
    238     do    {
    239         s = ans ;
    240         build(s) ;
    241         ans = kruskal(1) ;
    242     }while(fabs(ans-s) > EPS) ;
    243     return 1.0/ans ;
    244 }
    245 四、经典模型
    246 1.LICS平方算法
    247 int dp[MAXN][MAXN] ; // dp[i][j]表示a[1-i]到b[1-j]且以b[j]结尾的LCIS ;
    248 int dp_LCIS(){
    249     int i, j, max_l , ans = 0 ;
    250     for(i = 1 ; i <= m ; i ++) dp[0][i] = 0 ;
    251     for(i = 1 ; i <= n ; i ++)
    252     {
    253         max_l = 0 ;
    254         for(j = 1 ; j <= m ; j ++)
    255         {
    256             dp[i][j] = dp[i-1][j] ;
    257             if(a[i] > b[j]) max_l = max(max_l, dp[i-1][j]) ;
    258             //因为相当于a[i] > b[k]与b[j] > b[k]等价( >= 是非递减);
    259             if(a[i] == b[j]) dp[i][j] = max_l + 1 ;
    260         }
    261         ans = max(ans, dp[i][m]) ;
    262     }
    263     return ans ;
    264 }
    265 2.最长回文序列
    266 int solve(){ //最长回文子序列
    267     int i, j, tmp ; 
    268     memset(dp, 0, sizeof(dp)) ; 
    269     for(i = 1 ; i <= 3*n ; i ++) dp[i][i] = 1 ; 
    270     for(i = 3*n-1 ; i ; i --)
    271     {
    272         for(j = i+1 ; j <= 3*n ; j ++)
    273         {
    274             dp[i][j] = max(dp[i+1][j], dp[i][j-1]) ; 
    275             tmp = dp[i+1][j-1] + 2*(ar[i] == ar[j]) ; 
    276             dp[i][j] = max(dp[i][j], tmp) ; 
    277         }
    278     }
    279     int ans = 1 ; 
    280     for(i = n+1 ; i <= 2*n ; i ++) ans = max(ans, dp[i-n+1][i+n-1]) ;
    281     return ans ; 
    282 }
    283 3.最短编辑距离
    284 int solve(){//最短编辑距离
    285     int i, j, tmp, mx = max(ls, lt) ;
    286     for(i = 0 ; i <= ls ; i ++)
    287         for(j = 0 ; j <= lt ; j ++) dp[i][j] = mx ;
    288     for(i = 0 ; i <= mx ; i ++) dp[i][0] = dp[0][i] = i ;
    289     for(i = 1 ; i <= ls ; i ++ )
    290     {
    291         for(j = 1 ; j <= lt ; j ++)
    292         {
    293             tmp = min(dp[i-1][j]+1, dp[i][j-1]+1) ;
    294             if(s[i] == t[j]) dp[i][j] = min(dp[i][j], min(dp[i-1][j-1], tmp )) ;
    295             else dp[i][j] = min(dp[i][j], min(tmp, dp[i-1][j-1] + 1)) ;
    296         }
    297     }
    298     for(i = 1 ; i <= ls ; i ++) printf("%d ", dp[i][lt]) ; puts("") ;
    299     return dp[ls][lt] ;
    300 }
    301 4.最长公共子序列个数
    302 bool solve(){//最长公共子序列个数
    303     int i, j ; bool d = 0 ;
    304     memset(f[d], 0, sizeof(f[d])) ; memset(g[d], 0, sizeof(g[d])) ;
    305     for(i = max(n, m) ; i >= 0 ; i --) g[d][i] = 1 ;
    306     for(i = 1 ; i <= n ; i ++)
    307     {
    308         memset(f[!d], 0, sizeof(f[!d])) ; memset(g[!d], 0, sizeof(g[!d])) ;
    309         g[!d][0] = 1 ;
    310         for(j = 1 ; j <= m ; j ++)
    311         {
    312             if(s[i] == t[j])
    313             {
    314                 f[!d][j] = f[d][j-1] + 1 ;
    315                 g[!d][j] = g[d][j-1] ;
    316                 if(f[!d][j] == f[d][j])
    317                    g[!d][j] = (g[!d][j] + g[d][j]) % MOD ;
    318                 if(f[!d][j] == f[!d][j-1]) 
    319                    g[!d][j] = (g[!d][j] + g[!d][j-1]) % MOD ;
    320             }
    321             else            
    322              {
    323                 f[!d][j] = max(f[d][j], f[!d][j-1]) ;
    324                 if(f[!d][j] == f[d][j])
    325                    g[!d][j] = (g[!d][j] + g[d][j]) % MOD ;
    326                 if(f[!d][j] == f[!d][j-1]) 
    327                    g[!d][j] = (g[!d][j] + g[!d][j-1]) % MOD ;
    328                 if(f[!d][j] == f[d][j-1])
    329                    g[!d][j] = ( g[!d][j] - g[d][j-1] + MOD) % MOD ;
    330             }
    331         }
    332         d = !d ;
    333     }
    334     return d ;
    335 }
    View Code
  • 相关阅读:
    遗传算法求解TSP问题
    蚁群算法求解TSP问题
    遗传算法之函数优化
    k-means和iosdata聚类算法在生活案例中的运用
    MATLAB实现模糊控制
    感知机算法及BP神经网络
    K-means聚类算法
    链表_leetcode92
    链表_leetcode86
    链表_leetcode83
  • 原文地址:https://www.cnblogs.com/xieyue/p/4332351.html
Copyright © 2020-2023  润新知