8号做的hdu上面的题目重现。
A题:Wow! Such Doge!
题意:给你一篇文章,找出其中doge出现的次数,不区分大小写。
思路:字符串大写转小写的函数忘了……一个一个转的。然后find下,每次从find的位置开始找,统计个数就完了。交的时候调试忘记删除了,wa了一次。大水!
C题:Wow! Such City!
题意:用给定的数,通过公式可以求出任意两个城市间的距离。一个人在城市0,求出他到所有城市的最小距离。再用这个距离模M,模完的结果一样的放成一类,求MOD完最小的那类。
思路:一开始以为要快速幂什么的求呢,后来发现不用就一个一个求就好。求完所有的点,刷一下最短路(哎~我图论不好看见就蒙圈,最短路写了好久……渣渣啊~~)。再模下,找出最小的就完了。感觉也很水。
D题:Wow! Such String!
题意:很好懂。给一个N,求一个长度是N的字符串。所求字符串的所有长度大于4的子串不重复。有输出,没有Impossible。
思路:当时的思路是求出所有长度是4的不重复的串。然后把所有的串连成一个字符串(前串的后三个字符和后串的前三个字符相同)。处理的时候出了点小问题。我从aaaa开始拼接字符串,aaaab aaac aaad aaae ……aaayaaazaaa ,前面所有的aaa开头的串都用过了,无法把所有的字符串拼接到一起。然后我想换一个试试,当时好像换的zaaa开始的,长度变长了些但还是没有全部拼合。接下来不知道怎么做了,我又用zzzz开始试了下,奇迹的发现全部拼接完了(现在也不到为什么?),然后这个题就出了。
J题:Tunnels
题意:图上有好多通道(tunnels这个词不认识,英语是硬伤啊!),有个人要走遍所有的通道,每个通道只能通过一次。求最短时间?
思路:题目给出一共只有15个通道,当时想一共才2^15个状态,先BFS预处理求出任意两点之间的距离,再用next_permutation把所有的情况的时间都求一下找个最小的就搞定了。然后就各种RE,找到RE的地方是一个n*n + n超了。我开的数组是1000的,n才15不能超啊,不到原因啊,我恨死RE了。后来加个判定就是各种wa,实在调不出来了。完了看看大神的代码,发现思路基本一致,就是后面大神们用的状态压缩DP求得,我用的next_permutation。又写了写发现next_permutation超时了,不到这个坑爹的东西时间复杂度是多少。BFS的求点到点的距离也有些问题,各种小错误。哎,怀念芳姐啊~~有芳姐的话这题就不用我了啊……据说这就是旅行商问题,渣渣又学了一招。
贴上这个巨肯爹的代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <string>
using namespace std;
#define For(i,a) for(i=0;i<a;i++)
#define Foru(i,a,b) for(i=a;i<=b;i++)
#define Ford(i,a,b) for(i=a;i>=b;i--)
#define PB push_back
#define clr(a,vel) memset(a,vel,sizeof(a))
#define INF 0x7fffffff
const int MAXN = 17;
const int xa[] = {-1, 1, 0, 0};
const int ya[] = {0, 0, -1, 1};
int n, m;
char g[MAXN+4][MAXN+4];
bool id[MAXN+2][MAXN+2];
bool use[MAXN+2],vis[MAXN+2][MAXN+2];
int dp[1<<MAXN][MAXN];
int dis[MAXN][MAXN];
int sun[MAXN];
struct point{
int xs, ys, xe, ye;
}p[MAXN];
struct shortdis{
int x, y, dis;
};
inline void bfs(int pos){
clr(use, 0), clr(vis, 0);
shortdis vn, vm;
vn.x = p[pos].xe, vn.y = p[pos].ye, vn.dis = 0;
queue <shortdis> q;
q.push(vn);
int num = 0;
while(!q.empty()){
vn = q.front();
q.pop();
if(id[vn.x][vn.y]){
for(int i = 0; i < m; i ++){
if(vn.x == p[i].xs && vn.y == p[i].ys && !use[i] && i != pos){
dis[pos][i] = vn.dis;
use[i] = 1;
num ++;
}
}
}
if( num + 1 == m) return ;
for(int i = 0; i < 4; i ++) {
vm.x = vn.x + xa[i];
vm.y = vn.y + ya[i];
if(!vis[vm.x][vm.y] && g[vm.x][vm.y] == '.'){
vis[vm.x][vm.y] = 1;
vm.dis = vn.dis + 1;
q.push(vm);
}
}
}
}
int main(){
while( cin >> n >> m){
clr(id, 0), clr(g, -1);
clr(dp, -1), clr(dis, -1);
for(int i = 1; i <= n; i ++) scanf("%s",g[i]+1);
for(int i = 0; i < m; i ++){
cin >> p[i].xs >> p[i].ys >> p[i].xe >> p[i].ye;
id[p[i].xs][p[i].ys] = 1;
}
for(int i = 0; i < m; i ++) {
dis[i][i] = 0;
bfs(i);
//for(int j = 0; j < m; j ++) cout << dis[i][j] << ' '; cout << endl;
}
/* 我自己写的超时的next_permutation 感觉时间复杂度应该在2^n * n^2 可还是超了
for(int i = 0; i < m; i ++) sun[i] = i;
int j, pre, nxt, ans, sum;
ans = -1;
do{
pre = sun[0];
sum = 0;
for(j = 1; j < m; j ++){
nxt = sun[j];
if( dis[pre][nxt] == -1) {
sum = -1;
break;
}
sum += dis[pre][nxt];
pre = nxt;
}
//for(int j = 0; j < m; j ++) cout << sun[j] << ' ' ; cout << endl;
//cout << sum << endl;
if(sum == -1) continue;
else {
if(ans == -1) ans = sum;
else ans = min(ans,sum);
}
}while(next_permutation(sun,sun+m));
cout << ans << endl;
*/
int all = (1<<m);
//dp[0][0] = 0;
for(int i = 0; i < m; i ++) dp[1<<i][i] = 0;
for(int i = 0; i <= all; i ++){
for(int j = 0; j < m; j ++){
if(dp[i][j] != -1 && i & (1<<j) ){
// cout << i << ' ' << j << endl;
for(int k = 0; k < m; k ++) if(!(i&1<<k) && dis[j][k] != -1){
int nxt = i | (1<<k);
if(dp[nxt][k] == -1) dp[nxt][k] = dp[i][j] + dis[j][k];
else dp[nxt][k] = min(dp[nxt][k], dp[i][j] + dis[j][k]);
}
}
}
}
//for(int i = 0; i < m; i ++) cout << dp[all-1][i] << ' '; cout << endl;
int ans = -1;
for(int i = 0; i < m; i ++){
if(dp[all-1][i] != -1) {
if(ans == -1) ans = dp[all-1][i];
else ans = min(ans, dp[all-1][i]);
}
}
cout << ans << endl;
}
return 0;
}