IME Starters Try-outs 2018 C. China Adventures

C. China Adventures
time limit per test
1.0 s
memory limit per test
512 MB
input
standard input
output
standard output

The ACM ICPC World Finals is a huge event! On 2018 the World Finals was at Beijing, China.

The chinese culture is way different than brazilian culture. They eat

(as they translated: "Bad fish chips")

and

(as they translated: "Sauteed chicken on the left")

Their traffic is crazy, with cars driving on the cycle path, motorcycles driving the wrong way or on the sidewalk. But, the weirdest of all, they use QR-codes for everything.

A QR-code is a square image, in this case a 21×2121×21 pixel matrix, that each pixel is either black or white. The code carries some information, usually an URL or a text, and can be read by almost all modern smartphones.

They use QR-codes so that people don't have to copy text all the time. They just have to open their smartphone's camera and the magic happens.

During a tour on Beijing, Lucas Santana, the Handsome, noticed that to visit some tourist places he needed to know the QR-code to buy the tickets for that place. Since he's a very smart guy, he decided to create a mobile application to draw the QR-codes, instead of searching for them.

The mobile application works as follow: it starts with a 21×2121×21 white pixel matrix. You can click any pixel to swap it's color from white to black or from black to white in 1 decisecond. Also, you can restart the application at any time to have an all white pixel matrix again, but it take aa deciseconds to do so. When you complete the QR-code, you can assume you can enter the tourist place.

Lucas knows the QR-code of nn places he wants to visit. He doesn't care about the order he visits the places, but, since he only have a few days left on China, he wants to spend the least time as possible drawing the QR-codes. Can you help him saying the minimum amount of deciseconds to draw all nn QR-codes, the order he should visit the places and when he should restart the application?

He will not visit the same place more than once. (Don't even try this. He will give you a wrong answer!).

Input

The first line of input contains two integers, nn and aa (1n181≤n≤18, 1a501≤a≤50) — the number of places he wants to visit and the total time to restart the application.

The next lines contains the QR-codes of the places separated by empty lines. There will be nn QR-codes, each having 2121 lines of 2121 digits being 00 or 11. Digit 00 means a white pixel and 11 a black pixel.

Output

Print the minimum amount of deciseconds to draw all QR-codes followed by at least nn lines and at most 2×n12×n−1 lines. Each line should have one number between 11 and nn, meaning that he must visit the place ii, or one character "*" (without quotes), meaning that he must restart the application.

All numbers should be distinct.

If there are multiple answers, print any of them.

Example
input
Copy
1 10
111111100101101111111
100000101101001000001
101110101100101011101
101110100101001011101
101110101000101011101
100000101001101000001
111111101010101111111
000000001111100000000
110100110110001110110
111101000100000110110
111110111110101101101
001110001011001101001
000111110010110100100
000000001001000100000
111111101110011110110
100000100011110001000
101110100101011100010
101110101111000010011
101110100100100110101
100000101010011100000
111111101101100010010
output
Copy
228
1
Note

In sample case, he should just draw the only QR-code available and visit the place. The QR-code is:

思路:求出转移代价相当求一个哈密顿路,状压dp即可。

  1 #include <iostream>
  2 #include <fstream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <list>
 16 #include <iomanip>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <bitset>
 20 #include <ctime>
 21 
 22 using namespace std;
 23 
 24 #define pau system("pause")
 25 #define ll long long
 26 #define pii pair<int, int>
 27 #define pb push_back
 28 #define mp make_pair
 29 #define clr(a, x) memset(a, x, sizeof(a))
 30 
 31 const double pi = acos(-1.0);
 32 const int INF = 0x3f3f3f3f;
 33 const int MOD = 1e9 + 7;
 34 const double EPS = 1e-9;
 35 
 36 /*
 37 #include <ext/pb_ds/assoc_container.hpp>
 38 #include <ext/pb_ds/tree_policy.hpp>
 39 
 40 using namespace __gnu_pbds;
 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
 42 */
 43 
 44 int n, a;
 45 char s[22][22][22];
 46 vector<int> e[22];
 47 struct Edge {
 48     int v, w;
 49     Edge () {}
 50     Edge (int v, int w) : v(v), w(w) {}
 51 };
 52 int cal(char a[22][22], char b[22][22]) {
 53     int res = 0;
 54     for (int i = 1; i <= 21; ++i) {
 55         for (int j = 1; j <= 21; ++j) {
 56             res += a[i][j] != b[i][j];
 57         }
 58     }
 59     return res;
 60 }
 61 int cal2(char a[22][22]) {
 62     int dis = 0;
 63     for (int i = 1; i <= 21; ++i) {
 64         for (int j = 1; j <= 21; ++j) {
 65             dis += a[i][j] - '0';
 66         }
 67     }
 68     return dis;
 69 }
 70 int dp[1 << 20][20], dis[22][22];
 71 pii pre[1 << 20][20];
 72 int main() {
 73     scanf("%d%d", &n, &a);
 74     for (int i = 1; i <= n; ++i) {
 75         for (int j = 1; j <= 21; ++j) {
 76             scanf("%s", s[i][j] + 1);
 77         }
 78     }
 79     for (int i = 1; i <= n; ++i) {
 80         for (int j = i + 1; j <= n; ++j) {
 81             int d = cal(s[i], s[j]);
 82             dis[i][j] = dis[j][i] = d;
 83         }
 84     }
 85     for (int i = 1; i <= n; ++i) {
 86         int d = cal2(s[i]);
 87         dis[i][0] = dis[0][i] = d;
 88     }
 89     clr(dp, INF);
 90     dp[0][0] = 0;
 91     for (int i = 0; i < 1 << n; ++i) {
 92         for (int j = n; ~j; --j) {
 93             for (int k = 0; k <= n; ++k) {
 94                 if (!k) {
 95                     if (dp[i][k] > dp[i][j] + a) {
 96                         dp[i][k] = dp[i][j] + a;
 97                         pre[i][k] = pii(i, j);
 98                     }
 99                 }
100                 else {
101                     if (i & (1 << k - 1)) continue;
102                     int x = i | (1 << k - 1);
103                     if (dp[x][k] > dp[i][j] + dis[j][k]) {
104                         dp[x][k] = dp[i][j] + dis[j][k];
105                         pre[x][k] = pii(i, j);
106                     }
107                 }
108             }
109         }
110     }
111     int ans = INF;
112     pii pp;
113     for (int i = 0; i <= n; ++i) {
114         if (ans > dp[(1 << n) - 1][i]) {
115             ans = dp[(1 << n) - 1][i];
116             pp = pii((1 << n) - 1, i);
117         }
118     }
119     printf("%d\n", ans);
120     stack<pii> sta;
121     while (pp != pii(0, 0)) {
122         sta.push(pp);
123         int x = pp.first, y = pp.second;
124         pp = pre[x][y];
125     }
126     while (sta.size()) {
127         pp = sta.top(); sta.pop();
128         if (pp.second) {
129             printf("%d\n", pp.second);
130         } else {
131             puts("*");
132         }
133     }
134     return 0;
135 }
View Code

 

 

转载于:https://www.cnblogs.com/BIGTOM/p/9289790.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值