1. 程式人生 > >[uvalive 7263] Today Is a Rainy Day(暴力,BFS,dp)

[uvalive 7263] Today Is a Rainy Day(暴力,BFS,dp)

預處理 ini pen sta 現在 修改 ace printf main

題目鏈接:https://vjudge.net/problem/UVALive-7263

題意:給兩個字符串a,b,只包含1~6的數字,現在允許兩種操作:1、修改某一位數字,2、修改整個串的某個數字,變成另外一個數字。問從a到b的最少操作。

首先2操作修改的比較多,假如都能打到最優解的情況下,盡可能多的2操作一定會比較優。

我們可以先不考慮字符串具體的變化,先考慮只有6位數的2操作的變化情況。

以012345為起點,預處理出需要多少種2操作才可以變成一個6為的目標串。

不必關心每一種數字有多少個,只需要關心2操作最少多少次。上述操作直接bfs就行了。

接下來枚舉012345變成000000到555555的所有最小狀態作為中間狀態,由於1操作的存在,所以僅僅進行2操作是會多進行多余的操作的。因此要記下輸入字符串中每一種數字出現的次數,以及b到a每一對數字變化的次數。,用前者減去後者,加上枚舉到的中間狀態的最少步驟,求整個過程的最小值就是最優值。

 1 #pragma comment(linker, "/STACK:1024000000,1024000000")
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxn = 66666;
 6 const int inf = 0x7f7f7f7f;
 7 unordered_map<string, int> id;
 8 string di[maxn];
 9 int G[11][11], vis[11];
10 int icnt, n;
11 int dp[maxn];
12 string a, b;
13
queue<int> q; 14 string itmp; 15 16 void dfs(int cnt) { 17 if(cnt == 6) { 18 id[itmp] = icnt; di[icnt++] = itmp; 19 return; 20 } 21 for(int i = 0; i < 6; i++) { 22 string bk = itmp; 23 itmp += (i + 0); 24 dfs(cnt+1); 25 itmp = bk;
26 } 27 } 28 29 void init() { 30 string pre, cpy; 31 itmp.clear(); pre.clear(); id.clear(); icnt = 0; 32 dfs(0); 33 for(int i = 0; i < icnt; i++) dp[i] = inf; 34 for(int i = 0; i < 6; i++) pre += (i + 0); 35 while(!q.empty()) q.pop(); 36 q.push(id[pre]); dp[id[pre]] = 0; 37 while(!q.empty()) { 38 int pid = q.front(); q.pop(); 39 pre = di[pid]; 40 for(int i = 0; i < 6; i++) { 41 for(int j = 0; j < 6; j++) { 42 cpy = pre; 43 for(int k = 0; k < 6; k++) { 44 if(pre[k] == i + 0) cpy[k] = j + 0; 45 } 46 int cid = id[cpy]; 47 if(dp[cid] == inf) { 48 dp[cid] = dp[pid] + 1; 49 q.push(cid); 50 } 51 } 52 } 53 } 54 } 55 56 int main() { 57 // freopen("in", "r", stdin); 58 init(); 59 cout << di[15115] << " " << dp[15115] << endl; 60 while(cin >> a >> b) { 61 memset(G, 0, sizeof(G)); 62 memset(vis, 0, sizeof(vis)); 63 n = a.length(); 64 for(int i = 0; i < n; i++) { 65 int u = b[i] - 1; 66 int v = a[i] - 1; 67 G[u][v]++; vis[u]++; 68 } 69 int ret = inf; 70 for(int i = 0; i < icnt; i++) { 71 string mid = di[i]; 72 int tmp = dp[i]; 73 for(int j = 0; j < 6; j++) { 74 tmp += vis[j] - G[j][mid[j]-0]; 75 } 76 ret = min(ret, tmp); 77 } 78 printf("%d\n", ret); 79 } 80 return 0; 81 }

[uvalive 7263] Today Is a Rainy Day(暴力,BFS,dp)