剪枝是c[i] < ( n*m-cnt+1)/2 ,减掉很多没必要的搜索

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 7

using namespace std;

int a[MAX][MAX];
int c[MAX*MAX];
bool flag = false;
int t,n,m,k;

void dfs ( int cnt = 0 )
{
   // cout << cnt << endl;
    if ( cnt == n*m )
    {
        puts ("YES" );
        for ( int i = 1 ; i <= n ; i++ )
        {
            for ( int j = 1 ; j < m ; j++ ) printf ( "%d " , a[i][j] );
            printf ( "%d\n" , a[i][m] );
        }
        flag = true;
        return;       
    }
    for ( int i = 1 ; i <= k ; i++ )
        if ( c[i] > (n*m-cnt+1)/2 ) return;
    int x = cnt/m+1;
    int y = cnt%m+1;
    for ( int i = 1 ; i <= k ; i++ )
    {
        if ( flag ) return;
        if ( !c[i] ) continue;
        if(i==a[x-1][y]||i==a[x+1][y]||i==a[x][y+1]||i==a[x][y-1])
            continue;
        a[x][y] = i;
        c[i]--;
        dfs ( cnt + 1 );
        a[x][y] = 0;
        c[i]++;   
    }
}

int main ( )
{
    scanf ( "%d" , &t );
    int cc = 1;
    while ( t-- )
    {
        scanf ( "%d%d%d" , &n , &m , &k );
        for ( int i = 1 ; i <= k ; i++ ) scanf ( "%d" , &c[i] );
        printf ( "Case #%d:\n" , cc++ );
        memset ( a , 0 , sizeof ( a ) );
        flag = false;
        dfs ( );
        if ( !flag ) puts ( "NO" );
    }
}