//题意 貌似是求满意度的范围最小.
//顺便贴个以前找到的, 效率还算可以的最大流模板
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int MAXV = 1210;
const int MAXE = 1000010;
const int inf = 1 << 29;
int head[MAXV], N;
struct Edge {
    
    int v, next, w;
}edge[MAXE];
int n, m, s, t, cnt, ans;
void add(int u, int v, int w) {
    
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].next = head[ u ];
    head[ u ] = cnt++;
    
    edge[cnt].v = u;
    edge[cnt].w = 0;
    edge[cnt].next = head[ v ];
    head[ v ] = cnt++;
}
int sap() {
    
    int pre[MAXV], cur[MAXV], dis[MAXV], gap[MAXV];
    int flow = 0, aug = inf, u;
    bool flag;
    
    for(int i = 0; i <= N; ++ i) {
        
        cur[ i ] = head[ i ];
        gap[ i ] = dis[ i ] = 0;
    }
    
    gap[ s ] = N;
    u = pre[ s ] = s;
    
    while(dis[ s ] < N) {
        
        flag = 0;
        
        for(int &j = cur[ u ]; j != -1; j = edge[ j ].next) {
            
            int v = edge[ j ].v;
            
            if(edge[ j ].w > 0 && dis[ u ] == dis[ v ] + 1) {
                
                flag = 1;
                
                if(edge[ j ].w < aug) aug = edge[ j ].w;
                
                pre[ v ] = u;
                u = v;
                
                if(u == t) {
                    
                    flow += aug;
                    
                    while(u != s) {
                        
                        u = pre[ u ];
                        edge[cur[ u ]  ].w -= aug;
                        edge[cur[ u ]^1].w += aug;
                    }
                    aug = inf;
                }
                break;
            }
        }
        
        if(flag) continue;
        
        int mindis = N;
        
        for(int k = head[ u ]; k != -1; k = edge[ k ].next) {
            
            int v = edge[ k ].v;
            
            if(edge[ k ].w > 0 && dis[ v ] < mindis) {
                
                mindis = dis[ v ];
                cur[ u ] = k;
            }
        }
        
        if( (--gap[dis[ u ]]) == 0) break;
        
        dis[ u ] = mindis + 1;
        gap[dis[ u ]] ++;
        u = pre[ u ];
    }
    return flow;
}
int cap[30], i, j;
int mat[MAXV][30];
int main() {
    
    while(scanf("%d %d", &m, &n) != EOF) {
        
        for(i = 1; i <= m; ++ i) {
            
            for(j = 1; j <= n; ++ j) {
                
                scanf("%d", &mat[ i ][ j ]);
            }
        }
        
        for(i = 1; i <= n; ++ i) {
            
            scanf("%d", &cap[ i ]);
        }
        
        int left = 1, right = 1; int mmax = n;
        
        while(left <= n && right <= n) {
            
            
            s = 0; t = m + n + 1; cnt = 0; N = t + 1;
            memset(head,-1,sizeof(head));
            
            for(i = 1; i <= m; ++ i) {
                
                add(s, i, 1);
            }
            
            for(i = 1; i <= m; ++ i) {
                
                for(j = 1; j <= n; ++ j) {
                    
                    if(left <= j && j <= right) {
                        
                        add(i, mat[ i ][ j ]+m, 1);
                    }
                }
            }
            
            for(j = 1; j <= n; ++ j) {
                
                add(m+j, t, cap[ j ]);
            }
            
            ans = sap();
            
            if(ans == m) {
                
                if(mmax > right - left + 1) mmax = right - left + 1;
                left ++;
            }
            else right ++;
        }
        
        printf("%d\n", mmax);
    }
    return 0;
}