博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C. Dasha and Password 预处理 + dp
阅读量:4693 次
发布时间:2019-06-09

本文共 5359 字,大约阅读时间需要 17 分钟。

对于每一个字符串,可以预处理出其到达数字,字母,和特殊符号所需的最小步数。

然后就是在n个东西中,选出数字、字母和特殊符号,至少一个,所需的最少步数。

因为第一个选了数字的话,它就不能选字母的了,然后比赛的时候发现这就是二分图,然后就上了km的模板。(太笨了我)

虽然过了,但是明显正解不是这个。

#include 
#include
#include
#include
#include
#include
#define IOS ios::sync_with_stdio(false)using namespace std;#define inf (0x3f3f3f3f)typedef long long int LL;#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 500 + 20;char str[maxn][maxn];int e[200 + 20][200 + 20];int match[maxn];//match[col] = rowint vx[maxn], vy[maxn];int fx[maxn], fy[maxn];int dfs (int u, int m) { vx[u] = 1; int i; for (i = 1; i <= m; i++) { //筛选n个 导航员 col的值 if (vy[i] == 0 && fx[u] + fy[i] == e[u][i]) { vy[i] = 1; if (match[i] == 0 || dfs(match[i], m)) { match[i] = u; // match[col]=row; return 1;//搭配成功 } } } return 0;//我找不到啊,后面,就会执行km}void do_km(int n, int m) { // int i, j; int d = -inf; for (i = 1; i <= n; i++) { //遍历每一个驾驶员 row的值 if (vx[i] == 1) { for (j = 1; j <= m; j++) { //对他进行遍历导航员 col的值 if (!vy[j]) { if (d < (fx[i] + fy[j] - e[i][j])) { d = fx[i] + fy[j] - e[i][j]; } } } } } for (i = 1; i <= n; i++) { if (vx[i] == 1) { fx[i] -= d; vx[i] = 0; //请0 } if (vy[i] == 1) { // fy[i] += d; vy[i] = 0; //情0 } } return ;}int anskm(int n, int m) { memset(vx, 0, sizeof(vx)); memset(vy, 0, sizeof(vy)); memset(fx, 0, sizeof(fx)); memset(fy, 0, sizeof(fy)); memset(match, 0, sizeof(match)); //km算法的一部分,先初始化fx,fy for (int i = 1; i <= n; i++) { //遍历每一个驾驶员 row的值 fy[i] = 0; fx[i] = inf; //无穷小 for (int j = 1; j <= m; j++) { //遍历每一个导航员 col的值 if (fx[i] > e[i][j]) { //默契值 fx[i] = e[i][j]; } } } for (int i = 1; i <= n; i++) { //遍历每一个驾驶员 row的值 memset(vx, 0, sizeof(vx)); memset(vy, 0, sizeof(vy)); while (!dfs(i, m)) { //如果他找不到搭配,就实现km算法 do_km(n, m);//km完后,还是会对这个想插入的节点进行dfs的,因为他还没搭配嘛 } } int ans = 0; for (int i = 1; i <= m; i++) //遍历导航员,col的值 ans += e[match[i]][i];//输入的row是驾驶员,col是导航员 //match[i]:导航员i和驾驶员match[i]搭配了 match[col]=row; return ans;}void work() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= 200; ++i) { for (int j = 1; j <= 200; ++j) { e[i][j] = 500; } } for (int i = 1; i <= n; ++i) { scanf("%s", str[i] + 1); int a = 500, b = 500, c = 500; int len = m; for (int j = 1; str[i][j]; ++j) { if (str[i][j] >= '0' && str[i][j] <= '9') { a = min(a, j - 1); } else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') { b = min(b, j - 1); } else { c = min(c, j - 1); } } for (int j = len; j >= 1; j--) { if (str[i][j] >= '0' && str[i][j] <= '9') { a = min(a, len - j + 1); } else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') { b = min(b, len - j + 1); } else { c = min(c, len - j + 1); } } e[i][1] = a; e[i][2] = b; e[i][3] = c; }// for (int i = 1; i <= n; ++i) {// for (int j = 1; j <= n; ++j) {// cout << e[i][j] << " ";// }// cout << endl;// } cout << anskm(n, n) - (n - 3) * 500 << endl;}int main() {#ifdef local freopen("data.txt", "r", stdin);// freopen("data.txt", "w", stdout);#endif work(); return 0;}
km

正解因该是一个dp

dp[i][2][2]][2]表示在前i个字符串中,选出了数字(0 or 1)、字母、特殊符号所需的最小步数。

转移

dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a][b][c]); //保留上次的最小值。

然后对于每一个a、b、c

dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a - 1][b][c] + e[i][1]);之类的。

一开始还担心会不会使得同一个字符串,既选了数字,也选了字母。

然后是不会的,因为需要选数字的时候,是从dp[!now][a - 1][b][c]转移过来的,也就是从上一唯的b、c转过来。所以不会有重复。

#include 
#include
#include
#include
#include
#include
#define IOS ios::sync_with_stdio(false)using namespace std;#define inf (0x3f3f3f3f)typedef long long int LL;#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 500 + 20;char str[maxn][maxn];int e[200 + 20][200 + 20];int dp[2][2][2][2];void work() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= 200; ++i) { for (int j = 1; j <= 200; ++j) { e[i][j] = 500; } } for (int i = 1; i <= n; ++i) { scanf("%s", str[i] + 1); int a = 500, b = 500, c = 500; int len = m; for (int j = 1; str[i][j]; ++j) { if (str[i][j] >= '0' && str[i][j] <= '9') { a = min(a, j - 1); } else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') { b = min(b, j - 1); } else { c = min(c, j - 1); } } for (int j = len; j >= 1; j--) { if (str[i][j] >= '0' && str[i][j] <= '9') { a = min(a, len - j + 1); } else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') { b = min(b, len - j + 1); } else { c = min(c, len - j + 1); } } e[i][1] = a; e[i][2] = b; e[i][3] = c; } memset(dp, 0x3f, sizeof dp); int now = 0; dp[now][0][0][0] = 0; for (int i = 1; i <= n; ++i) { now = !now; for (int a = 0; a <= 1; ++a) { for (int b = 0; b <= 1; ++b) { for (int c = 0; c <= 1; ++c) { dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a][b][c]); if (a) { dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a - 1][b][c] + e[i][1]);// break; } if (b) { dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a][b - 1][c] + e[i][2]);// break; } if (c) { dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a][b][c - 1] + e[i][3]);// break; } } } } } cout << dp[now][1][1][1] << endl;}int main() {#ifdef local freopen("data.txt", "r", stdin);// freopen("data.txt", "w", stdout);#endif work(); return 0;}
View Code

 

转载于:https://www.cnblogs.com/liuweimingcprogram/p/6359892.html

你可能感兴趣的文章
Chukwa
查看>>
(转)Maven仓库——私服介绍
查看>>
设计模式之工厂模式
查看>>
仿复制粘贴功能,长按弹出tips的实现
查看>>
Kubernetes-Host网络模式应用
查看>>
第三次作业
查看>>
使用HTML5构建iOS原生APP(2)
查看>>
sqlplus terminators - Semicolumn (;), slash (/) and a blank line
查看>>
省选知识清单/计划列表(咕?)
查看>>
远程桌面(3389)复制(拖动)文件
查看>>
转 lucene3搜索引擎,索引建立搜索排序分页高亮显示, IKAnalyzer分词
查看>>
bootstrap datetimepicker 位置错误
查看>>
9结构型模式之代理模式
查看>>
第二节 整型数据
查看>>
Python 序列
查看>>
Liferay的架构:缓存(第一部分)
查看>>
初识B/S结构编程技术
查看>>
方法、hadoop源码之JobQueueTaskScheduler-by小雨
查看>>
页面重构总结
查看>>
IO 函数
查看>>