摘要: #include <iostream>#include <cstdio>#include <cstring>#pragma comment(linker,"/STACK:655360000");using namespace std;const int N = 1002;int f[N], rank[N];int find(int x){ int k, r, j; r = x; while(r != f[r]) { r = f[r]; } k = x; while(k != r) { j = f[k]; ... 阅读全文
posted @ 2011-09-06 11:23 AC_Von 阅读(152) 评论(0) 推荐(0) 编辑
摘要: 又是一道纠结的dp题,做dp快做的崩溃了。。。状态表示:Dp[i][j]为前i个月的留j个人的最优解;Num[i]<=j<=Max{Num[i]};j>Max{Num[i]}之后无意义,无谓的浪费记Max_n=Max{Num[i]};Dp[i-1]中的每一项都可能影响到Dp[i],即使Num[i-1]<<Num[i]所以利用Dp[i-1]中的所有项去求Dp[i];对于Num[i]<=k<=Max_n,当k<j时,招聘; 当k>j时,解雇然后求出最小值Dp[i][j]=min{Dp[i-1][k…Max_n]+(招聘,解雇,工资); 代码:# 阅读全文
posted @ 2011-09-05 21:14 AC_Von 阅读(171) 评论(0) 推荐(0) 编辑
摘要: 大连网络赛之前做的一次模拟赛上见到,开始想用贪心做,但没想到好的贪心策略,之后放下。这几天又重新看了看这道题,有看了看网上的题解,终于把这题A了!。思路:如图:布的总大小为(xx, yy)。剪下的面积为(x, y); 注意这句话: a machine which can cut one cloth into exactly two smaller rectangular pieces horizontally or vertically所以可行的剪法有四种,即:由上图可得动态转移方程为:dp[i][j] = max(dp[i][j], dp[i-x][j] + dp[x][j-y] + c.. 阅读全文
posted @ 2011-09-05 14:44 AC_Von 阅读(237) 评论(0) 推荐(0) 编辑
摘要: 刚拿到这题时很纠结,没有思路。后来想了一天,问了问高手终于把思路整理出来。思路:三个瓶子,无非就是6种倒法,按杯子体积从大到小定义为s, m, n。则6种倒法分别是:s -> m, s -> n, m -> n, m -> s, n -> m, n -> s;加一个标记变量,标记当前状态已经出现过。将没出现过的状态入队列,剩下的就是bfs的事了。。。My Code:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const 阅读全文
posted @ 2011-09-02 21:49 AC_Von 阅读(254) 评论(0) 推荐(0) 编辑
摘要: 这题用bfs做的,总结出来一条真理!在用bfs时,如果要引用结构体定义中的值,一定加中间变量,不要直接在上边操作。思路:直接用bfs找终点,如果中途遇到map[i][j] == 4的点,就把time置为6, 把走过的map[i][j] == 4的点标记为0;My Code:#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct nightmare{ int i; int j; int t; int step;}q[10000];int d[4][2] = 阅读全文
posted @ 2011-09-02 19:33 AC_Von 阅读(189) 评论(0) 推荐(0) 编辑
摘要: 此题做的相当爽,为什么爽呢,因为。。。连带TLE, RE, WA。总共错了11次。。。有一个地方没考虑清楚,然后再怎么剪枝都WA,最后ZZ一句话惊醒梦中人,总于A了。思路:这题要求方向改变次数。用一个变量记录上一次的方向,与下一次向比较,如果不同则加1。My Code:#include <iostream>#include <cstdio>#include <cstring>#define ud 1; //标记上下方向#define lr 2; //标记左右方向using namespace std;int map[1005][1001]; //存放每次询问 阅读全文
posted @ 2011-09-02 15:56 AC_Von 阅读(294) 评论(0) 推荐(0) 编辑
摘要: 这题做了将近一个月,断断续续的看背包问题,今天总于一口气把背包九讲中的前三讲看完了。这个一个很典型的多重背包问题:第i件物品有n[i]种,所占的容量权值分别是c[i],w[i]。求最大容量为V时所得到的最大权值。按照背包九讲的讲解,可以利用二进制思想,把n[i]个物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。(1.....n[i]中的任意一个 阅读全文
posted @ 2011-08-31 13:52 AC_Von 阅读(351) 评论(0) 推荐(0) 编辑
摘要: 1. 背包问题介绍背包问题不单单是一个简单的算法问题,它本质上代表了一大类问题,这类问题实际上是01线性规划问题,其约束条件和目标函数如下:自从dd_engi在2007年推出《背包问题九讲》之后,背包问题的主要精髓基本已道尽。本文没有尝试对背包问题的本质进行扩展或深入挖掘,而只是从有限的理解(这里指对《背包问题九讲》的理解)出发,帮助读者更快地学习《背包问题九讲》中的提到的各种背包问题的主要算法思想,并通过实例解释了相应的算法,同时给出了几个背包问题的经典应用。2. 背包问题及应用dd_engi在《背包问题九讲》中主要提到四种背包问题,分别为:01背包问题,完全背包问题,多重背包问题,二维费用 阅读全文
posted @ 2011-08-31 10:41 AC_Von 阅读(583) 评论(0) 推荐(0) 编辑
摘要: //打星号的表示个人认为比较经典,或是算法比较好的题目共80题,各种类型,背包,树形dp,状态dp。。。。1014* Dividing半个背包,注意中断 √1036 Gangsters √f[i]表示第i个人成功进入后,前i个人的最优值。。。 f[i]由f[j]转移来,(0 <= j < i)。。。。注意T和S的值符合逻辑,一个250的错误,搞掉好几次wa。。。1038* Bugs Integrated, Inc.状态压缩 √ http://www.cnblogs.com/vongang/archive/2012/07/30/2615322.html 1050 To the Max 阅读全文
posted @ 2011-08-30 20:15 AC_Von 阅读(1012) 评论(0) 推荐(0) 编辑
摘要: 这两天快被DP整崩溃啦!!!今天拿到这道题也是无从下手,问了下高手思路才做出来。思路:开另个数组on[], off[]。分别表示开Caps Lock灯,和关Caps Lock灯时的最小按键次数当字符串s[i]为大写时: on[i] = min{ on[i-1] + 1, off[i-1] + 2} //开灯时直接输入字母,关灯时按shift+字母; off[i] = min{ on[i-1] + 2, off[i-1] + 2} //开灯时先输字母再关灯,关灯时按shift+字母;当字符串s[i]为小写时: on[i] = min{ on[i-1] + 2, off[i-1] + 2... 阅读全文
posted @ 2011-08-30 20:12 AC_Von 阅读(224) 评论(0) 推荐(0) 编辑
摘要: 这个题目与最长上升子序类问题类似,刚开始想用贪心做了,但是悲剧的连题目给的数据都没过。后来想DP,由于最近在看背包问题,思维僵化,怎么想也想不出怎么套背包的转移方程。问了下高手,才猛然想起来这题的思路,我悲剧的一晚上啊。。。。代码:#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;const int N = 31;struct blocks{ int l; int w; int h; int s;}b[N*6];int dp[N*6];int cmp(const 阅读全文
posted @ 2011-08-28 22:07 AC_Von 阅读(216) 评论(0) 推荐(0) 编辑
摘要: 前几天挺gbx说有个11级的小同学,已经在某OJ上刷过1000多道题,倍受打击!一度感叹为什么我没有早点起步,甚至一度认为ACM是给那些初高中做过NOI的同学准备的。 今天突发神经查了查神牛HH 的简历,真的很震撼:胡浩刚进入大学时,学院就给大一新生介绍了ACM大赛,胡浩对ACM的狂热由此而生。“高中的时候,学校没有信息学,我什么都不懂,只是单纯地对这件事感兴趣。”为了能够进入学校的ACM集训队,他开始埋头钻研。学校限制大一新生带电脑,胡浩就去网吧做题,经常连续好几个晚上通宵。 网吧里充斥着游戏玩家的叫喊声、键盘的敲击声以及各种游戏的背景音乐,胡浩却独自沉浸在ACM的世界里。就这样... 阅读全文
posted @ 2011-08-28 20:01 AC_Von 阅读(820) 评论(0) 推荐(1) 编辑
摘要: ps:这两天忙着搬宿舍都快忙晕了,今天终于有空复习一下01背包问题。对动态规划不熟,方法还是看的解题报告。还是根据01背包的动态转移方程:dp[j] = max{dp[j], dp[j-c[i]] + w[i]}。只不过这里要做一下转变,将银行的总钱数作为背包容量V,每个银行的钱数作为c[i],抢每个银行不被抓住的概率作为w[i]。结构体定义struct node{ int money; double p;}r[N]动态转移方程改为:dp[j] = max{dp[j], dp[j-r[i].money]*(1-r[i].p)}。也就是求不被抓住的概率最大。代码如下:#include <. 阅读全文
posted @ 2011-08-27 19:38 AC_Von 阅读(249) 评论(0) 推荐(0) 编辑
摘要: 链表实现:struct node{ int v; //边的结束顶点int w; //边的长度 node* next; //指向以同一起点的下一条边的指针}*first[N]; //first[u]指向以u为起始点的第一条边void init(){ memset(first,NULL,sizeof(first));}void add(int u, int v, int w)//添加边{ node* p =new node; p->v = v; p->w = w; p->next = fisrt; first[u] = p;}//使用的时候,找u的邻接点for(no... 阅读全文
posted @ 2011-08-24 20:05 AC_Von 阅读(2782) 评论(0) 推荐(1) 编辑
摘要: 并查集(Union-Find Sets),字面意思理解——合并,查找。给出一个集合,将其合并后用一个点代替一个集合的元素。例如:1 22 34 3合并后就是 2 / \1 3 \ 4主要操作:1、查找。2、合并。查找方法见http://www.cnblogs.com/vongang/archive/2011/07/31/2122763.html合并实现方法如下:void Union(int root1, int root2){ int x = FindSet(root1), y = FindSet(root2); if( x == y ) return ; if( ... 阅读全文
posted @ 2011-08-24 17:42 AC_Von 阅读(277) 评论(0) 推荐(0) 编辑
摘要: 下图说的很清楚,每次找入度为0的点,将其从序列中删掉,同时与它相连的所有点入度减一;实现代码,以HUD_1285为例:#include <iostream>#include <cstdio>using namespace std;const int N = 501;int map[N][N];int into[N], ans[N];void toposort(int x){ int i, j, k; for(i = 1; i <= x; i++) for(j = 1; j <= x; j++) if(map[i][j]) ... 阅读全文
posted @ 2011-08-24 17:25 AC_Von 阅读(243) 评论(0) 推荐(0) 编辑
摘要: 开始没整明白,还想用dfs递归求解,后来看了看解题报告的思路(貌似这题可以用dp),bfs一遍,用一个best[i]存放到i的最优解,最后直接输出best[k]就行。第一次队列数组开小(还是不想用<queue>)了,WA了一次。。。#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 100007;int q[N*10];int best[N];int n, k;void bfs(){ int f = 0, r = 0, x, 阅读全文
posted @ 2011-08-24 11:35 AC_Von 阅读(174) 评论(0) 推荐(0) 编辑
摘要: 代码+注释:#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int N = 100;int s[N];bool used[N];int cmp(int a, int b){ return a > b;}bool dfs(int n, int u, int left, int len){//n是木棍的总数//u是未被拼到长度为len的原始木棍中木棍数目//left是当前正在拼的木棍的剩余长度//len是正在尝试的原始木棍的长度 if(lef 阅读全文
posted @ 2011-08-24 09:59 AC_Von 阅读(206) 评论(0) 推荐(0) 编辑
摘要: 纠结一晚上,注意细节啊!!!(看到有很多解题报告都用<queue>,我不太喜欢用STL的东西。。。)My Code:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 51;struct node{ int x; int y; int z; int t;}q[N*N*N];int d[6][3] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, -1}, {0, 阅读全文
posted @ 2011-08-22 22:05 AC_Von 阅读(322) 评论(0) 推荐(0) 编辑
摘要: 字典树(Trie树),可以将之归为高级数据结构吧,黑书上把Trie树和线段树一起讲的。之所以叫它字典树,大概是因为它的结构太像字典了。就像这张图片:由字符串 abcd、abd、bcd、efg、hi。建成的Trie树如上图所示(Trie树大概的结构一看就能理解);Trie树的主要操作:1、建立新节点(姑且算是一样吧);2、插入(建树);3、查找(与树中的字符串匹配,这个过程是肯快的,如果能完全匹配的时间复杂度为是O(n),n = strlen(s)。)Trie的实现:1、结构体定义:struct node{ int flag; //标记 node * next[26]; ... 阅读全文
posted @ 2011-08-22 09:00 AC_Von 阅读(667) 评论(0) 推荐(0) 编辑
摘要: Trie水题,将每个单词插入Trie树,然后暴力拆分每个单词到树中查找匹配即可!有几个要注意的细节,代码注释中都标上了。My Code:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAX = 50007;struct node{ int flag; node * next[26];};char dis[MAX][30];node * newnode(){ int i; node * p = new node; p->flag = 阅读全文
posted @ 2011-08-21 21:12 AC_Von 阅读(296) 评论(0) 推荐(0) 编辑
摘要: 题意:这题很好理解,给一个字典,上边有火星文对应的英语,让后输入一句话,把它翻译成英语。 思路:定义Tire树时加一个存放字符串的数组s[],按字典上的火星文建立Trie树,在每一个火星文的末尾将对应的英文存到s[]中。查找时如果能在Trie树中找到,就将s[]对应的串取出来(至于怎么取,自己先想想。。。)分解输入的句子时注意细节。还有就是静态建立Trie树,我开始用动态,WA了。。。My Code:#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>us 阅读全文
posted @ 2011-08-21 19:05 AC_Von 阅读(529) 评论(0) 推荐(0) 编辑
摘要: 要输出最长上升子序列,只需加一个pre数组,记录新加如序列的前一个。最后遍历一遍数组就可以。代码如下:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 1000;int num[N];int pre[N];int dp[N];int f[N];int main(){ freopen("data.in", "r", stdin); int n, i, j, ans, flag; while(~sc 阅读全文
posted @ 2011-08-21 09:34 AC_Von 阅读(1431) 评论(0) 推荐(0) 编辑
摘要: Hash思想,因为题目要求第K大的数,可能很多人会想到先从小到大排序,然后找到第k个数。但是,注意,|xi - xj|可能会出想重复,也就是说排好序还得处理重复。Hash的大体思路是:将|xi - xj|作为一个hash数组的下标,如果hash[|xi - xj|]为空则hash[|xi - xj|]++;查找第k大时直接遍历一遍hash数组就行;代码:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 2007;int a[N/2]; 阅读全文
posted @ 2011-08-20 10:17 AC_Von 阅读(271) 评论(0) 推荐(1) 编辑
摘要: 一位ACMer过来人的心得(转载)刻苦的训练我打算最后稍微提一下。主要说后者:什么是有效地训练? 我想说下我的理解。 很多ACMer入门的时候,都被告知:要多做题,做个500多道就变牛了。其实,这既不是充分条件、也不会是必要条件。 我觉得一般情况下,对于我们普通学校的大学生,各方面能力的差距不会太大,在这种情况下,训练和学习的方法尤为重要。 其实,500题仅仅是一个标志,而且仅仅表示你做ACM-ICPC有一定的时间, 我们训练的目的是什么?我觉得有四点 1、提高编程能力 2、学习算法,(读书,读论文,包括做一些题目验证) 3、准备好面临将到来的挑战(熟悉题型,调整心态) 4、启发思维。 这里四 阅读全文
posted @ 2011-08-20 09:45 AC_Von 阅读(500) 评论(0) 推荐(1) 编辑