C. Dasha and Password 预处理 + dp
http://codeforces.com/contest/761/problem/C
对于每一个字符串,可以预处理出其到达数字,字母,和特殊符号所需的最小步数。
然后就是在n个东西中,选出数字、字母和特殊符号,至少一个,所需的最少步数。
因为第一个选了数字的话,它就不能选字母的了,然后比赛的时候发现这就是二分图,然后就上了km的模板。(太笨了我)
虽然过了,但是明显正解不是这个。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = + ;
char str[maxn][maxn];
int e[ + ][ + ]; int match[maxn];//match[col] = row
int vx[maxn], vy[maxn];
int fx[maxn], fy[maxn];
int dfs (int u, int m) {
vx[u] = ;
int i;
for (i = ; i <= m; i++) { //筛选n个 导航员 col的值
if (vy[i] == && fx[u] + fy[i] == e[u][i]) {
vy[i] = ;
if (match[i] == || dfs(match[i], m)) {
match[i] = u; // match[col]=row;
return ;//搭配成功
}
}
}
return ;//我找不到啊,后面,就会执行km
}
void do_km(int n, int m) { //
int i, j;
int d = -inf;
for (i = ; i <= n; i++) { //遍历每一个驾驶员 row的值
if (vx[i] == ) {
for (j = ; 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 = ; i <= n; i++) {
if (vx[i] == ) {
fx[i] -= d;
vx[i] = ; //请0
}
if (vy[i] == ) { //
fy[i] += d;
vy[i] = ; //情0
}
}
return ;
}
int anskm(int n, int m) {
memset(vx, , sizeof(vx));
memset(vy, , sizeof(vy));
memset(fx, , sizeof(fx));
memset(fy, , sizeof(fy));
memset(match, , sizeof(match));
//km算法的一部分,先初始化fx,fy
for (int i = ; i <= n; i++) { //遍历每一个驾驶员 row的值
fy[i] = ;
fx[i] = inf; //无穷小
for (int j = ; j <= m; j++) { //遍历每一个导航员 col的值
if (fx[i] > e[i][j]) { //默契值
fx[i] = e[i][j];
}
}
}
for (int i = ; i <= n; i++) { //遍历每一个驾驶员 row的值
memset(vx, , sizeof(vx));
memset(vy, , sizeof(vy));
while (!dfs(i, m)) {//如果他找不到搭配,就实现km算法
do_km(n, m);//km完后,还是会对这个想插入的节点进行dfs的,因为他还没搭配嘛
}
}
int ans = ;
for (int i = ; 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 = ; i <= ; ++i) {
for (int j = ; j <= ; ++j) {
e[i][j] = ;
}
}
for (int i = ; i <= n; ++i) {
scanf("%s", str[i] + );
int a = , b = , c = ;
int len = m;
for (int j = ; str[i][j]; ++j) {
if (str[i][j] >= '' && str[i][j] <= '') {
a = min(a, j - );
} else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') {
b = min(b, j - );
} else {
c = min(c, j - );
}
}
for (int j = len; j >= ; j--) {
if (str[i][j] >= '' && str[i][j] <= '') {
a = min(a, len - j + );
} else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') {
b = min(b, len - j + );
} else {
c = min(c, len - j + );
}
}
e[i][] = a;
e[i][] = b;
e[i][] = 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 - ) * << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}
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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = + ;
char str[maxn][maxn];
int e[ + ][ + ];
int dp[][][][];
void work() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= ; ++i) {
for (int j = ; j <= ; ++j) {
e[i][j] = ;
}
}
for (int i = ; i <= n; ++i) {
scanf("%s", str[i] + );
int a = , b = , c = ;
int len = m;
for (int j = ; str[i][j]; ++j) {
if (str[i][j] >= '' && str[i][j] <= '') {
a = min(a, j - );
} else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') {
b = min(b, j - );
} else {
c = min(c, j - );
}
}
for (int j = len; j >= ; j--) {
if (str[i][j] >= '' && str[i][j] <= '') {
a = min(a, len - j + );
} else if (str[i][j] == '#' || str[i][j] == '*' || str[i][j] == '&') {
b = min(b, len - j + );
} else {
c = min(c, len - j + );
}
}
e[i][] = a;
e[i][] = b;
e[i][] = c;
}
memset(dp, 0x3f, sizeof dp);
int now = ;
dp[now][][][] = ;
for (int i = ; i <= n; ++i) {
now = !now;
for (int a = ; a <= ; ++a) {
for (int b = ; b <= ; ++b) {
for (int c = ; c <= ; ++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 - ][b][c] + e[i][]);
// break;
}
if (b) {
dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a][b - ][c] + e[i][]);
// break;
}
if (c) {
dp[now][a][b][c] = min(dp[now][a][b][c], dp[!now][a][b][c - ] + e[i][]);
// break;
}
}
}
}
}
cout << dp[now][][][] << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}
C. Dasha and Password 预处理 + dp的更多相关文章
- Codeforces Round #394 (Div. 2) C. Dasha and Password(简单DP)
C. Dasha and Password time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Codeforces Round #394 (Div. 2) C. Dasha and Password 暴力
C. Dasha and Password 题目连接: http://codeforces.com/contest/761/problem/C Description After overcoming ...
- Codeforces Round #394 (Div. 2) C. Dasha and Password
C. Dasha and Password time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Codeforces 761C Dasha and Password(枚举+贪心)
题目链接 Dasha and Password 题目保证一定有解. 考虑到最多只有两行的指针需要移动,那么直接预处理出该行移动到字母数字或特殊符号的最小花费. 然后O(N^3)枚举求最小值即可. 时间 ...
- Div.2 C. Dasha and Password
C. Dasha and Password time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Codeforces Round #394 (Div. 2) C. Dasha and Password —— 枚举
题目链接:http://codeforces.com/problemset/problem/761/C C. Dasha and Password time limit per test 2 seco ...
- codeforces 761 C. Dasha and Password(多维dp)
题目链接:http://codeforces.com/contest/761/problem/C 题意:给出n行的字符串每一列都从第一个元素开始可以左右移动每一行字符串都是首位相连的. 最后问最少移动 ...
- BZOJ-1587|前缀和 预处理 dp||叶子合并leaves
叶子合并leaves Description 在一个美丽的秋天,丽丽每天都经过的花园小巷落满了树叶,她决定把树叶堆成K堆,小巷是笔直的 共有N片树叶(树叶排列也是笔直的),每片树叶都有一个重量值,并且 ...
- 2013-2014 ACM-ICPC, NEERC, Southern Subregional Contest Problem H. Password Service dp
Problem H. Password Service 题目连接: http://www.codeforces.com/gym/100253 Description Startups are here ...
随机推荐
- Django:视图和URL配置
一.视图 1.在mysite文件夹下.创建views.py文件(文件名称没有特别的要求): from django.http import HttpResponse def hello(re ...
- 解决centos yum安装"No package nginx available."问题
问题原因: nginx位于第三方的yum源里面,而不在centos官方yum源里面 解决方法: 安装epel(Extra Packages for Enterprise Linux) a.去epel网 ...
- 【翻译自mos文章】oracle db 中的用户账户被锁--查看oracle用户的尝试次数
參考原文: Users Accounts Getting Locked. (Doc ID 791037.1) 事实上这个文章是为oracle 别的软件产品写的,只是涉及到user 锁定问题.那还是跟d ...
- 本人会linux系统的各种版本的安装,近期发教程
小弟虽然刚刚踏入职场,可是咱大学也不是打酱油过的啊,研究过各种版本系统的安装,也都均已经实践,勿喷,有问题 咱们可以相互探讨!
- [IT学习]跟阿铭学linux(第3版)
1.安装Linux在虚拟化平台上 Windows Vmware Workstation,需要在本机上打开CPU对虚拟化的支持.Virtualization Cent OS7 已成功安装. 2.http ...
- nginx与apache 对比 apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程
nginx与apache详细性能对比 http://m.blog.csdn.net/lengzijian/article/details/7699444 http://www.cnblogs.com/ ...
- Rod Johnson
Spring Framework创始人,著名作者. Rod在悉尼大学不仅获得了计算机学位,同时还获得了音乐学位.更令人吃惊的是在回到软件开发领域之前,他还获得了音乐学的博士学位. 有着相当丰富的C/C ...
- 【Codeforces 915E】 Physical Education Lessons
[题目链接] 点击打开链接 [算法] 线段树,注意数据量大,要动态开点 [代码] #include<bits/stdc++.h> using namespace std; ; ,root ...
- JSP 注释的详解及简单实例
转自:https://www.jb51.net/article/124727.htm JSP 注释的详解及简单实例 一 三种格式 二 举例 ? 1 2 3 4 5 6 7 8 9 10 11 12 1 ...
- java笔记之IO4文本复制
* 复制文本文件. * * 数据源:从哪里来 * a.txt -- 读取数据 -- FileInputStream * * 目的地:到哪里去 * b.txt -- 写数据 -- FileOut ...