pku 3614

我用网络流过了,呵呵,SAP很强大。

 

#include <stdio.h>
#include <string.h>
#define oo 0x7fffffff
#define MAXM 690000
#define MAXN 5003
typedef struct{int u; int v; int cap; int next;}edge_t;
edge_t e[MAXM * 2];
int first[MAXN];
int dist[MAXN];
int now[MAXN];
int pre[MAXN];
int cnt[MAXN];
int cur[MAXN];
int tot, n;
void add(int u, int v, int cap)
{
	e[++tot].u = u; e[tot].v = v; e[tot].cap = cap; e[tot].next = first[u]; first[u] = tot;
	e[++tot].u = v; e[tot].v = u; e[tot].cap = 0; e[tot].next = first[v]; first[v] = tot;
}
void init()
{
	int covers, spf, st, ed;
	int c, l, i, j;
	scanf("%d %d", &c, &l);
	for(i = 1;i <= c; i++) scanf("%d %d", &cnt[i], &cur[i]);
	memset(first, -1, sizeof(first)); tot = -1;
	st = 1;
	ed = c + l + 2;
	for(i = 1;i <= l; i++)
	{
		scanf("%d %d", &spf, &covers);
		add(st, i + 1, covers);
		for(j = 1;j <= c; j++) if(cnt[j] <= spf && spf <= cur[j]) add(i + 1, l + j + 1, oo);
	}
	for(i = 1;i <= c; i++) add(l + i + 1, ed, 1);
	n = ed;
}
int sap()
{
	int tot_flow;
	int now_flow, found, min;
	int st, ed, i, j, t;
	memset(dist, 0, sizeof(dist));
	memset(now, -1, sizeof(now));
	memset(cnt, 0, sizeof(cnt));
	st = 1; ed = n; i = st;
	tot_flow = 0; now_flow = oo;
	cnt[0] = n;
	while(dist[st] < n)
	{
		cur[i] = now_flow; found = 0;
		if(now[i] == -1) t = first[i];
		else t = now[i];
		while(t != -1)
		{
			j = e[t].v;
			if(e[t].cap > 0 && dist[j] + 1 == dist[i])
			{
				found = 1; now[i] = t;
				if(e[t].cap < now_flow) now_flow = e[t].cap;
				pre[j] = t; i = j;
				if(i == ed)
				{
					tot_flow += now_flow;
					while(i != st)
					{
						e[pre[i]].cap -= now_flow;
						e[pre[i]^1].cap += now_flow;
						i = e[pre[i]].u;
					}
					now_flow = oo;
				}
				break;
			}
			t = e[t].next;
		}
		if(found) continue;
		if(--cnt[dist[i]] == 0) break;
		min = n - 1;
		t = first[i];
		while(t != -1)
		{
			if(e[t].cap > 0 && dist[e[t].v] < min)
			{
				min = dist[e[t].v];
				now[i] = t;
			}
			t = e[t].next;
		}
		dist[i] = min + 1;
		cnt[dist[i]]++;
		if(i != st)
		{
			i = e[pre[i]].u;
			now_flow = cur[i];
		}
	}
	return tot_flow;
}
int main()
{
	int res;
	init();
	res = sap();
	printf("%d\n", res);
	return 0;
}

 

 

.emacs

开始使用emacs

先贴个.emacs

 

 

(setq indent-tabs-mode nil)
(setq default-tab-width 4)
(setq tab-width 4)
(setq tab-stop-list ())

;;set c program style
(add-hook 'c-mode-hook 'linux-c-mode)
(setq imenu-sort-function 'imenu--sort-by-name)
(defun linux-c-mode()
 (define-key c-mode-map [return] 'newline-and-indent)
 (interactive)
 (c-set-style "K&R")
 (c-toggle-hungry-state)
 (setq c-basic-offset 4)
 (imenu-add-menubar-index)
 (which-function-mode)
)
;;set cpp program style
(add-hook 'c++-mode-hook 'linux-cpp-mode)
(setq imenu-sort-function 'imenu--sort-by-name)
(defun linux-cpp-mode()
 (define-key c++-mode-map [return] 'newline-and-indent)
 (interactive)
  (c-set-style "K&R")
  (c-toggle-hungry-state)
 (setq c-basic-offset 4)
 (imenu-add-menubar-index)
 (which-function-mode)
)

;;关闭烦人的出错时的提示声。
(setq visible-bell t)

;;关闭起动时候的那个“开机画面”
(setq inhibit-startup-message t)

;;显示列号
(setq column-number-mode t)

;;高亮显示匹配的括号
(show-paren-mode 1)

;;光标靠近鼠标指针时,让鼠标指针自动让开,别挡住视线。
(mouse-avoidance-mode 'animate)

;;指针不闪,不恍花眼睛。
(blink-cursor-mode -1)
(transient-mark-mode 1)

;;语法加亮
(global-font-lock-mode t)

;;光标显示为一竖线
(setq-default cursor-type 'bar)

;; 不显示工具栏
(tool-bar-mode -1)

;;设置背景色和字体色
(set-foreground-color "grey")
(set-background-color "black")

;; 隐藏滚动条
(scroll-bar-mode -1)
;;滚动条在右侧
(set-scroll-bar-mode 'right)

;; 不产生备份文件,临时文件
(setq make-backup-files nil)
(setq-default make-backup-files nil)
;;关闭自动保存模式
(setq auto-save-mode nil)
;;关闭#filename#临时文件
(setq auto-save-default nil)

;; 支持emacs和外部程序的粘贴
(setq x-select-enable-clipboard t)

;; 给每行显示行号: http://stud4.tuwien.ac.at/~e0225855/linum/linum.html
(require 'linum)           
(global-linum-mode t)

(create-fontset-from-fontset-spec
 (concat
  "-*-DejaVu Sans Mono-medium-r-normal-*-14-*-*-*-*-*-fontset-courier,"))
 (set-default-font "fontset-courier")

 

 

pku 1164

这道题其实就是求连通块的个数,及最大的连通块,题目输入表示一个块四周的墙要处理下,将块的表示数字分别与1, 2, 4, 8相与得到在W,N,E,S是否有墙。

代码如下:

 

#include <stdio.h>
#include <string.h>
#define MAXN 102
char map[MAXN][MAXN];
int mask[4] = {1, 2, 4, 8};
int dx[4] = {0, -1, 0, 1};
int dy[4] = {-1, 0, 1, 0};
int cnt, max, tot, n, m;
void init()
{
	int x, y, i, j, k, p;
	scanf("%d %d", &n, &m);
	memset(map, '#', sizeof(map));
	for(i = 1;i <= n; i++)
	{
		for(j = 1;j <= m; j++)
		{
			scanf("%d", &p);
			x = i << 1;
			y = j << 1;
			map[x][y] = ' ';
			for(k = 0;k < 4; k++)
				if((p & mask[k]) == 0) map[x + dx[k]][y + dy[k]] = ' ';
		}
	}
	n <<= 1; n++;
	m <<= 1; m++;
}
void dfs(int x, int y)
{
	int tx, ty, i;
	map[x][y] = '*';
	if(x % 2 == 0 && y % 2 == 0) cnt++;
	for(i = 0;i < 4; i++)
	{
		tx = x + dx[i];
		ty = y + dy[i];
		if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
		if(map[tx][ty] != ' ') continue;
		dfs(tx, ty);
	}
}
void solve()
{
	int i, j;
	tot = 0;
	max = 0;
	for(i = 1;i <= n; i++)
	{
		for(j = 1;j <= m; j++)
		{
			if(map[i][j] == ' ')
			{
				tot++;
				cnt = 0;
				dfs(i, j);
				if(max < cnt) max = cnt;
			}
		}
	}
	printf("%d\n", tot);
	printf("%d\n", max);
}
int main()
{
	init();
	solve();
	return 0;
}

 

 

pku 1166

这题我用位运算+bfs过了,时间有些长,这题还可以用数学方法:高斯消元。

代码:

 

#include <stdio.h>
#include <string.h>
#define BITAT(x,i) (((x)>>(9-(i)))&1)
#define MAXN 1<<20
int mask[10] = {0, 432, 448, 216, 292, 186, 73, 54, 7, 27};
int pre[MAXN][2];
int que[MAXN];
int head, tail, st;
void init()
{
	int i, x;
	st = 0;
	for(i = 1;i <= 9; i++)
	{
		scanf("%d", &x);
		st = (st<<2) | x;
	}
}
void bfs()
{
	int cur, tmp, i, j, k, t;
	memset(pre, -1, sizeof(pre));
	que[0] = st;
	head = 0;
	tail = 1;
	while(head < tail)
	{
		cur = que[head];
		for(j = 1;j <= 9; j++)
		{
			tmp = 0;
			for(i = 1;i <= 9; i++)
			{
				k = (cur>>(18 - i * 2)) & 3;
				t = BITAT(mask[j], i);
				k = (k + t) - (((k + t)>>2)<<2);
				tmp = (tmp<<2) | k;
			}
			if(pre[tmp][0] == -1)
			{
				pre[tmp][0] = cur;
				pre[tmp][1] = j;
				if(tmp == 0) return;
				que[tail++] = tmp;
			}
		}
		head++;
	}
}
void output()
{
	int i, j;
	i = 0; j = 0;
	while(i != st)
	{
		que[++j] = pre[i][1];
		i = pre[i][0];
	}
	for(i = j;i > 1; i--) printf("%d ", que[i]);
	printf("%d\n", que[1]);
}
int main()
{
	init();
	bfs();
	output();
	return 0;
}

 

 

代码2:

 

#include <stdio.h>
#include <string.h>
#define MAXN 1<<20
int act[9][9] = {{1, 1, 0, 1, 1, 0, 0, 0, 0},
	         {1, 1, 1, 0, 0, 0, 0, 0, 0},
	         {0, 1, 1, 0, 1, 1, 0, 0, 0},
		 {1, 0, 0, 1, 0, 0, 1, 0, 0},
		 {0, 1, 0, 1, 1, 1, 0, 1, 0},
		 {0, 0, 1, 0, 0, 1, 0, 0, 1},
		 {0, 0, 0, 1, 1, 0, 1, 1, 0},
		 {0, 0, 0, 0, 0, 0, 1, 1, 1},
		 {0, 0, 0, 0, 1, 1, 0, 1, 1}};
int pre[MAXN][2];
int que[MAXN];
int head, tail, st;
void init()
{
	int i, x;
	st = 0;
	for(i = 1;i <= 9; i++)
	{
		scanf("%d", &x);
		st = (st<<2) | x;
	}
}
void bfs()
{
	int cur, tmp, i, j, k, t;
	memset(pre, -1, sizeof(pre));
	que[0] = st;
	head = 0;
	tail = 1;
	while(head < tail)
	{
		cur = que[head];
		for(i = 1;i <= 9; i++)
		{
			tmp = 0;
			for(j = 1;j <= 9; j++)
			{
				k = (cur>>(18 - j * 2)) & 3;
				t = act[i-1][j-1];
				k = (k + t) - (((k+t)>>2)<<2);
				tmp = (tmp<<2) | k;
			}
			if(pre[tmp][0] == -1)
			{
				pre[tmp][0] = cur;
				pre[tmp][1] = i;
				if(tmp == 0) return;
				que[tail++] = tmp;
			}
		}
		head++;
	}
}
void output()
{
	int i, j;
	i = 0; j = 0;
	while(i != st)
	{
		que[++j] = pre[i][1];
		i = pre[i][0];
	}
	for(i = j;i > 1; i--) printf("%d ", que[i]);
	printf("%d\n", que[1]);
}
int main()
{
	init();
	bfs();
	output();
	return 0;
}

 

 

pku 3185

这道题与以前的一道翻转棋的类似,我用二进制表示状态,用异或运算实现一个状态到令一个状态的转移。

代码:

 

#include <stdio.h>
#include <string.h>
#define MAXM 1<<21
#define MAXN 20
int act[MAXN] = { 3, 7, 14, 28, 56, 112, 224, 448, 896, 1792, 3584, 7168, 14336, 28672, 57344, 114688, 229376, 458752, 917504, 786432 };
int que[MAXM];
int dis[MAXM];
int head, tail;
int st;
void init()
{
	int i, x;
	for(st = 0, i = 1;i <= 20; i++)
	{
		scanf("%d", &x);
		st = st * 2 + x;
	}
}
void bfs()
{
	int i, j, t;
	memset(dis, -1, sizeof(dis));
	dis[st] = 0;
	que[0] = st;
	head = 0;
	tail = 1;
	while(head < tail)
	{
		i = que[head];
		for(j = 0;j < 20; j++)
		{
			t = i ^ act[j];
			if(dis[t] == -1)
			{
				dis[t] = dis[i] + 1;
				if(t == 0) return;
				que[tail++] = t;
			}
		}
		head++;
	}
}
int main()
{
	init();
	bfs();
	printf("%d\n", dis[0]);
	return 0;
}