还蛮有趣的一道状态DP的题目。
1 /* 435B */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 #include <iterator> 20 #include <iomanip> 21 using namespace std; 22 //#pragma comment(linker,"/STACK:102400000,1024000") 23 24 #define sti set<int> 25 #define stpii set<pair<int, int> > 26 #define mpii map<int,int> 27 #define vi vector<int> 28 #define pii pair<int,int> 29 #define vpii vector<pair<int,int> > 30 #define rep(i, a, n) for (int i=a;i<n;++i) 31 #define per(i, a, n) for (int i=n-1;i>=a;--i) 32 #define clr clear 33 #define pb push_back 34 #define mp make_pair 35 #define fir first 36 #define sec second 37 #define all(x) (x).begin(),(x).end() 38 #define SZ(x) ((int)(x).size()) 39 #define lson l, mid, rt<<1 40 #define rson mid+1, r, rt<<1|1 41 42 const int maxn = 65; 43 int mask[maxn]; 44 bool visit[maxn]; 45 int P[maxn]; 46 const int m = 16; 47 const int N = (1<<m)+5; 48 const int INF = 0x1f1f1f1f; 49 int dp[105][N]; 50 int path[105][N]; 51 int a[105]; 52 53 void init() { 54 int i, j, k = 0; 55 56 for (i=2; i<maxn; ++i) { 57 if (!visit[i]) { 58 P[k++] = i; 59 for (j=i*i; j<maxn; j+=i) 60 visit[j] = true; 61 } 62 } 63 64 for (i=1; i<maxn; ++i) { 65 for (j=0; j<m; ++j) { 66 if (i%P[j] == 0) { 67 mask[i] |= (1<<j); 68 } 69 } 70 } 71 72 #ifndef ONLINE_JUDGE 73 printf("P[%d] = %d ", m, P[m]); 74 #endif 75 } 76 77 int main() { 78 ios::sync_with_stdio(false); 79 #ifndef ONLINE_JUDGE 80 freopen("data.in", "r", stdin); 81 freopen("data.out", "w", stdout); 82 #endif 83 84 init(); 85 int n; 86 87 scanf("%d", &n); 88 rep(i, 1, n+1) 89 scanf("%d", &a[i]); 90 91 int i, j, k; 92 int st, tmp; 93 int mxs = 1<<16; 94 95 memset(dp, 0x1f, sizeof(dp)); 96 memset(dp[0], 0, sizeof(int)*N); 97 for (i=1; i<=n; ++i) { 98 for (j=0; j<mxs; ++j) { 99 for (k=1; k<=60; ++k) { 100 if (j & mask[k]) 101 continue; 102 tmp = dp[i-1][j] + abs(a[i] - k); 103 st = j | mask[k]; 104 if (dp[i][st] > tmp) { 105 dp[i][st] = tmp; 106 path[i][st] = k; 107 } 108 } 109 } 110 } 111 112 int mn = INT_MAX, v; 113 114 for (j=0; j<mxs; ++j) { 115 if (dp[n][j] < mn) { 116 mn = dp[n][j]; 117 v = j; 118 } 119 } 120 121 vi ans; 122 123 for (i=n; i>0; --i) { 124 k = path[i][v]; 125 ans.pb(k); 126 v ^= mask[k]; 127 } 128 129 for (i=n-1; i>=0; --i) 130 printf("%d ", ans[i]); 131 putchar(' '); 132 133 #ifndef ONLINE_JUDGE 134 printf("time = %d. ", (int)clock()); 135 #endif 136 137 return 0; 138 }