找最长的其实是很裸的状态压缩DP,棘手的地方是要统计数量,其实只要再来一个数组存就好。
不过代码比较长,细节要注意的地方毕较多,wa了很多发,还是要仔细啊
用递推和记忆化搜索分别写了一遍
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn = 14;
const int INF = INT_MAX / 3;
int n,m,dist[maxn][maxn];
LL v[maxn];
LL f[maxn][maxn][1 << 14];
LL cnt[maxn][maxn][1 << 14];
void solve() {
    memset(f,-1,sizeof(f));
    memset(cnt,0,sizeof(cnt));
    int maxstate = (1 << n) - 1; //init
    for(int i = 0;i < n;i++) {
        for(int j = 0;j < n;j++) if(dist[i][j]) {
            int s = (1 << i) | (1 << j);
            f[i][j][s] = v[i] * v[j] + v[i] + v[j];
            cnt[i][j][s] = 1;
        }
    }
    //dp
    LL ans = 0,ct = 0;
    for(int s = 0;s <= maxstate;s++) {
        for(int i = 0;i < n;i++) if(s & (1 << i)) {
            for(int j = 0;j < n;j++) if(dist[i][j] && (s & (1 << j)) && f[i][j][s] != -1) {
                for(int k = 0;k < n;k++) if(dist[j][k] && !(s & (1 << k))) {
                    int ns = s | (1 << k);
                    LL &nowstate = f[i][j][s],&nextstate = f[j][k][ns];
                    LL &nowcnt = cnt[i][j][s],&nextcnt = cnt[j][k][ns];
                    LL addv = v[j] * v[k] + v[k];
                    if(dist[i][k]) addv += v[i] * v[j] * v[k];
                    if(nowstate + addv > nextstate) {
                        nextstate = nowstate + addv;
                        nextcnt = nowcnt;
                    }
                    else if(nowstate + addv == nextstate) {
                        nextcnt += nowcnt;
                    }
                }
                if(s == maxstate) {
                    if(f[i][j][s] > ans) {
                        ans = f[i][j][s];
                        ct = cnt[i][j][s];
                    }
                    else if(f[i][j][s] == ans) {
                        ct += cnt[i][j][s];
                    }
                }
            }
        }
    }
    if(ans == 0) cout << "0 0" << endl;
    else cout << ans << " " << ct / 2 <<  endl;
}
int main() {
    //freopen("in.txt","r",stdin);
    int T; scanf("%d",&T);
    while(T--) {
        memset(dist,0,sizeof(dist));
        scanf("%d%d",&n,&m);
        for(int i = 0;i < n;i++) cin >> v[i];
        for(int i = 0;i < m;i++) {
            int a,b; cin >> a >> b;
            a--; b--;
            dist[a][b] = dist[b][a] = 1;
        }
        if(n == 1) cout << v[0] << " " << 1 << endl;
        else solve();
    }
    return 0;
}
1 #include <cstdio> 2 #include <sstream> 3 #include <fstream> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 #include <map> 8 #include <cctype> 9 #include <ctime> 10 #include <set> 11 #include <climits> 12 #include <vector> 13 #include <queue> 14 #include <stack> 15 #include <cstdlib> 16 #include <cmath> 17 #include <string> 18 #include <list> 19 20 #define INPUT_FILE "in.txt" 21 #define OUTPUT_FILE "out.txt" 22 23 using namespace std; 24 25 typedef long long LL; 26 const int INF = INT_MAX / 2; 27 28 void setfile() { 29 freopen(INPUT_FILE,"r",stdin); 30 freopen(OUTPUT_FILE,"w",stdout); 31 } 32 33 const int maxn = 13; 34 35 int n,maxstate; 36 LL w[maxn][maxn],c[maxn]; 37 LL note[maxn][maxn][1 << 13]; 38 LL cnt[maxn][maxn][1 << 13]; 39 40 LL dfs(int prev,int now,int state) { 41 if(state == maxstate) return note[prev][now][state] = 0; 42 LL ret = -1,nret; 43 if(note[prev][now][state] != -1) { 44 return note[prev][now][state]; 45 } 46 for(int i = 0;i < n;i++) { 47 if((state & (1 << i)) == 0 && w[now][i] != -1) { 48 LL addv = w[now][i] + c[i]; 49 if(w[prev][i] != -1) addv += c[i] * c[prev] * c[now]; 50 nret = dfs(now,i,state | (1 << i)) + addv; 51 if(nret > ret) { 52 ret = nret; 53 } 54 } 55 } 56 if(ret == -1) return -INF * 100000LL; 57 return note[prev][now][state] = ret; 58 } 59 60 LL getcount(int prev,int now,int state) { 61 if(state == maxstate) return 1; 62 if(cnt[prev][now][state] != -1) return cnt[prev][now][state]; 63 LL ret = 0; 64 for(int i = 0;i < n;i++) { 65 if((state & (1 << i)) == 0 && w[now][i] != -1) { 66 LL addv = w[now][i] + c[i]; 67 if(w[prev][i] != -1) addv += c[i] * c[prev] * c[now]; 68 if(note[prev][now][state] == note[now][i][state | (1 << i)] + addv) { 69 ret += getcount(now,i,state | (1 << i)); 70 } 71 } 72 } 73 return cnt[prev][now][state] = ret; 74 } 75 76 int main() { 77 int T; 78 cin >> T; 79 while(T--) { 80 memset(w,-1,sizeof(w)); 81 memset(cnt,-1,sizeof(cnt)); 82 memset(note,-1,sizeof(note)); 83 int m; 84 cin >> n >> m; 85 for(int i = 0;i < n;i++) { 86 cin >> c[i]; 87 } 88 for(int i = 0;i < m;i++) { 89 int u,v; 90 cin >> u >> v; 91 u--; v--; 92 w[u][v] = w[v][u] = c[u] * c[v]; 93 } 94 maxstate = (1 << n) - 1; 95 LL ans = 0,ccnt = 0; 96 for(int i = 0;i < n;i++) { 97 for(int j = 0;j < n;j++) if(i != j && w[i][j] != -1) { 98 LL ret = dfs(i,j,(1<<i)|(1<<j)) + w[i][j] + c[i] + c[j]; 99 ans = max(ans,ret); 100 } 101 } 102 for(int i = 0;i < n;i++) { 103 for(int j = 0;j < n;j++) { 104 if(note[i][j][(1 << i)|(1 << j)] + w[i][j] + c[i] + c[j] == ans) { 105 ccnt += getcount(i,j,(1<<j)|(1<<i)); 106 } 107 } 108 } 109 if(n == 1) cout << c[0] << " " << 1 << endl; 110 else if(ccnt == 0) cout << "0 0" << endl; 111 else cout << ans << " " << ccnt / 2 << endl; 112 } 113 return 0; 114 }
POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP,布布扣,bubuko.com
POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP
原文:http://www.cnblogs.com/rolight/p/3867620.html