我终于找到了rp守恒定律的完整论文

“人品既不能被创生,也不能被消灭。只能从一个人转移到另一个人,从一个层面转化到另一个层面,而在转移和转化的过程当中,人品的总和保持不变。至此引出人品学(Characterics)三定律:

第一定律:即人品守恒定律,在任何过程中,宇宙中人品总量保持为常数。(也就是说,做好事增加人品做坏事损人品,遇到好事是以前积攒的人品起了作用,而要使你连自己系开的必修课都没选上,那你真的要多扶扶老奶奶过马路了)

第二定律:不可能把人品从一个人品低的人传到一个人品高的人,而不引起其它变化。(也就是说,人品低的想获得人品需要付出一定的代价,而请客吃饭等就是其最简单易行的途径。)

第三定律:不能用有限的步骤使一个人的人品完全消耗。(也就是说,你再怎么霉,也还是会有点人品存量的,所以永远不要灰心丧气。)请大家看一个范例:「塞翁的马丢了,他说“没事,攒人品”,当他丢失的马带回来一群马,别人羡慕不已,他则暗叹“不妙,人品消耗的太多”,果然他的儿子因为骑马而摔断了腿后,他摇摇头说“继续攒人品”,等到战争时别人家的孩子被征兵战死沙场,只有他的儿子因为腿断了而幸免,这时他激动地说“人品爆发了啊”……」

而现在的人品学家们在人品学理论的微观研究上已取得了革命性突破,在量子力学、大一统论、超弦理论大旗号召下的今天,让我们一起走进量子人品学(Quantum Characterics)的新纪元!

又发现的另外一种表述:

1)RP第一定律——RP守恒定律
RP是不能用科学原理和自然规律解释的一种非物质存在形式,一切不能用上述机理解释的问题,全部归类于RP问题。RP不能凭空生成,也不会凭空消失。它在自然界的总和一定。在一定时期,某个静态有机体所含有的RP一定。消耗RP,RP值降低,积攒RP,RP值升高。

2)RP第二定律——RP传递定律
RP只能自发地从RP高的物体传到RP低的物体,反之不成立。如果要使上述情况成立,必须消耗好人卡,公式:
RP = Num.好人卡/ 客观条件 + 机遇。

3)RP第三定律——RP数值定律
RP最小值为零,最大值正无穷, 物理意义上不存在负RP.

[人品的定义]: 从广义上说,但凡科学无法确定的的,不在科学所能接受范畴之内的现象均可用人品来给出解释,即人品是涵盖宏观和微观世界的客观存在;从狭义上说,人品也称为运势,通过个体衍生至全部,从而影响整个宇宙的发展。

[人品的性质]:
人品是客观存在的,不以人的意志为转移;人品是无处不在,无所不能的;人品是绝对的,不受任何外力的影响。

[人品守恒定律]:
宇宙的总人品是恒定的,有些人人品值高了,另一些人的人品值便会相应降低;个人的总人品在某一时间段内是恒定的,今天人品值低了,改天便会相应增高,但没有固定的期限。

[人品转移定律]:
人品是可以相互转移的,但这种转移必须通过必要的手段,譬如烧香,祈祷,诅咒等,以及相应的媒介,譬如遭遇高僧或者超级霉人。

[人品统计定律]:对于个体事件,人品是极不确定的,或不可量度的;然而对于大量的事件而言,人品会体现一定的统计规律。

人品与获得满足的关系:
导论:人品作为一般等价物,为满足日常需要,需投入一定的人品,以投入人品与获得的效用的数据构建图像,可以得到基数人品论(cardinal characterics)的边际人品-效用图。后来,有学者提出人品不可测量,只可比较,由此发展了序数人品论(ordinal characterics),目前比较成熟完善的是基数人品论。

基数人品论的一些观点:

1.为提高享受,需不断追加人品消耗,而享受的提高因随追加人品的增加而递减,享受提高为零时,投入人品就应停止,如再增加,则成为负数。即“人品效率递减定律”。表达式:dU/dRP<0

2.人品等分配定律:当面临多种消耗人品的活动时,应使得花费在所有活动的最后一单位人品边际效用相等。这样能将给定的人品转化出最大效用。表达式:dUk/dRPk=dU(k+1)/dRP(k+1),k∈N。

3.在原有人品消费已满足的前提下,要想用人品换取更多的好处,只有发展新人品消费项目和扩充原有人品消费项目。

规模人品:消费人品的活动,必须根据它的特点,确立一个起始人品投入规模/最小人品投入规模或称“最小有效规模”,投入低于这一规模,就会导致回报为零。超过这一规模,即进入一个“合理规模”区间,在这一区间内,追加人品投入都会得到回报。

人品爆发:一定条件下,存在以单位最小人品投入量获得最大单位的收益的点,称为“人品爆发点”。

但这种事件的发生时间、场所等往往难以确定。

由人品等分配定律可得,单位最小人品投入量获得最大单位的收益的点就是起始点。“人品爆发点”与之矛盾,如何解释呢?后经科学家赵明毅(?-2007)研究,人品爆发原因是他的故土–锑星星球有重要关系。锑星特有物质磷化卤(R?P),理化特性由于赵明毅的离奇失踪(?)而流失。其独特的的反重力性(探佚专家自《大锑赵明毅》相关章节推出)使得部分游离态磷化卤会脱离锑星,被喷射出去,从而对人品分布产生干扰,导致部分时间与场人品运行机理扭曲。由于历史原因,人品爆发常被归结于行善,现在这个概念已由国际人品研究协会(International Characteric Research Association,GCRA)规范化,形成了目前的通用表述与解释。

阅读全文

POJ1043

先上题目吧

What’s In A Name?

**Time Limit:** 1000MS **Memory Limit:** 10000K
**Total Submissions:** 1614 **Accepted:** 547

Description

The FBI is conducting a surveillance of a known criminal hideout which serves as a communication center for a number of men and women of nefarious intent. Using sophisticated decryption software and good old fashion wiretaps, they are able to decode any e-mail messages leaving the site. However, before any arrest warrants can be served, they must match actual names with the user ID’s on the messages. While these criminals are evil, they’re not stupid, so they use random strings of letters for

their ID’s (no dillingerj ID’s found here). The FBI knows that each criminal uses only one ID. The only other information they have which will help them is a log of names of the people who enter and leave the hideout. In many cases, this is enough to link the names to the ID’s.

Input

Input consists of one problem instance. The first line contains a single positive integer n indicating the number of criminals using the hideout. The maximum value for n will be 20. The next line contains the n user ID’s, separated by single spaces. Next will be the log entries in chronological order. Each entry in the log has the form type arg , where type is either E, L or M: E indicates that criminal arg has entered the hideout; L indicates criminal arg has left the hideout; M indicates a message was intercepted from user ID arg. A line containing only the letter Q indicates the end of the log. Note that not all user ID’s may be present in the log but each criminal name will be guaranteed to be in the log at least once. At the start of the log, the hideout is presumed to be empty. All names and user ID’s consist of only lowercase letters and have length at most

  1. Note: The line containing only the user ID’s may contain more than 80 characters.

Output

Output consists of n lines, each containing a list of criminal names and their corresponding user ID’s, if known. The list should be sorted in alphabetical order by the criminal names. Each line has the form name:userid , where name is the criminal’s name and userid is either their user ID or the string ??? if their user ID could not be determined from the surveillance log.

Sample Input

7 <br></br>bigman mangler sinbad fatman bigcheese frenchie capodicapo <br></br>E mugsy <br></br>E knuckles <br></br>M bigman <br></br>M mangler <br></br>L mugsy <br></br>E clyde <br></br>E bonnie <br></br>M bigman <br></br>M fatman <br></br>M frenchie <br></br>L clyde <br></br>M fatman <br></br>E ugati <br></br>M sinbad <br></br>E moriarty <br></br>E booth <br></br>Q 

Sample Output

Hint

bonnie:fatman

booth:???

clyde:frenchie

knuckles:bigman

moriarty:???

mugsy:mangler

ugati:sinbad

Source

这是一道二分图匹配的题目,一开始的时候想到了构图的办法,但是弄完图之后没有想到用二分图匹配,而是用了自己想出来的一个烂办法,结果就是WA,想到了一个反例又看了Discuss之后确信了用二分图匹配可以做。

构图方法是先置所有边为1,然后按顺序扫描输入,当某人发出一个信息的时候,说明只可能是当前正在房间里面的人发出信息,于是就把发出信息的这个人与所有不在房间里面的人连接的边删掉,之后就能得到一个二分图。

对于这个二分图,肯定是有一个完备匹配的。然后扫描二分图的每一条边,如果删了这条边之后不存在完备匹配说明这条边必须有,也就确定了一个name与id的关系了。

具体写的时候用了大量STL……发现STL还是挺方便的……就是一改C的简洁风格,每次写for(map<string, string>::iterator i = a.begin(); i!= a.end(); ++i)都感觉要崩溃……然后for_each又要自己写个函数类……单单这句话看起来是清爽了些,但是整体来看又是个乱七八糟的函数类,还是一次性的,每个循环都要写个函数类……悲剧……吐槽一下……不知道C++0x有没有改进……如果有了C#的lamda表达式之类的东西那应该方便很多……

另外好久没写匈牙利算法了,自己写出来之后感觉还行,也不是很乱,但是之后百度了一下别人的匈牙利算法……发现比我整整短了一倍……看起来也舒服……大悲剧……

贴代码先……

#include #include <map> #include #include using namespace std;

int n, nowIn[21], ans[21], now, a[21][21];//a[i][j]=0表示可能,1表示可能
int match[41], searched[41];

int dfs(int k)
{
for(int i=n+1; i<=n2; i++)
if(a[k][i-n] == 1 && match[i] == 0){
match[i] = k;
match[k] = i;
return i;
}
for(int i=n+1; i<=n
2; i++)
if(a[k][i-n] == 1 && searched[i] == 0){
searched[k] = searched[i] = 1;
int ret = dfs(match[i]);
searched[k] = searched[i] = 0;
if(ret != 0){
match[i] = k;
match[k] = i;
return i;
}
}
return 0;
}

int pipei()
{
int ret = 0;
fill_n(match, 41, 0);
fill_n(searched, 41, 0);
for(int i=1; i<=n ; ++i){
if(dfs(i))
++ret;
}
return ret;
}

int main()
{
string name[21],ID[21];
map<string, int> name2n,ID2n;
cin » n;
for(int i=1; i<=n; i++){
cin » name[i];
name2n[name[i]] = i;
}
fill_n(nowIn, 21, 0);
fill_n(a[0], 21*21, 1);
string s1, s2;
now = 0;
while(true){
cin » s1;
if(s1 == “Q”)
break;
cin » s2;
if(s1 == “E”){
if(ID2n[s2] == 0){
ID2n[s2] = ++now;
ID[now] = s2;
}
nowIn[ID2n[s2]] = 1;
}
if(s1 == “L”)
nowIn[ID2n[s2]] = 0;
if(s1 == “M”) {
for (int i = 1; i <= n; ++i){
if (nowIn[i] == 0)
a[name2n[s2]][i] = 0;
}
}
}
fill_n(ans, 21, 0);
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(a[i][j] == 1){
a[i][j] = 0;
if(pipei() != n)
ans[i] = j;
a[i][j] = 1;
}
if(ans[i] != 0)
break;
}
}
map<string, string> aa;
int i = 0;
for(int i=1; i<=n; ++i)
aa[ID[i]] = “???”;
for(int i=1; i<=n; i++)
if(ans[i] != 0)
aa[ID[ans[i]]] = name[i];
for(map<string, string>::iterator j = aa.begin(); j!= aa.end(); ++j)
cout « j->first « ”:” « j->second « endl;
return 0;
}

贴上百度来的匈牙利算法

#include #include

using namespace std;

int n1, n2, m, ans;
int result[101]; //记录V2中的点匹配的点的编号
bool state [101]; //记录V2中的每个点是否被搜索过
bool data[101][101];//邻接矩阵 true代表有边相连
void init()
{
int t1, t2;
memset(data, 0, sizeof(data));
memset(result, 0, sizeof(result));
ans = 0;
scanf(“ %d%d%d”, &n1, &n2, &m);
for (int i = 1; i <= m; i++)
{
scanf(“%d%d”, &t1, &t2);
data[t1][t2] = true;
}
return;
}
bool find(int a)
{
for (int i = 1; i <= n2; i++)
{
if (data[a][i] == 1 && !state[i]) //如果节点i与a相邻并且未被查找过
{
state[i] = true; //标记i为已查找过
if (result[i] == 0 //如果i未在前一个匹配M中
|| find(result[i])) //i在匹配M中,但是从与i相邻的节点出发可以有增广路
{
result[i] = a; //记录查找成功记录
return true; //返回查找成功
}
}
}
return false;
}
int main()
{
init();
for (int i = 1; i <= n1; i++)
{
memset(state, 0, sizeof(state)); //清空上次搜索时的标记
if (find(i)) ans++; //从节点i尝试扩展
}
printf(“%d\n”, ans);
return 0;
}

阅读全文

记网易有道难题在线赛

这次比赛题目改了,时间改了,规则改了,连测试数据都改了……

先总结一下,再写流水账……

两个字形容这次比赛就是难,乱

有人建议比赛改名“有三道难题”

题目很难,场面很混乱,网易有道先后上演了改题目,改规则,改时间,改数据……

另:ACRush大牛,太强悍了……膜拜Orz

题目地址

http://poj.youdao.com/nanti4/

7点比赛准时开始

看了第一道题目,看不懂

看了第二道题目,看懂了,感觉肯定做不出来,要是能写出来我就写个CYSQL去……

看了第三道题目,也看懂了,不过明显感觉挺难的,还带高精度……不高精度都想不到办法……

先想了一下第三题看看能不能想出个算法来,想来想去想不到,时间过了半个多小时了

回到第一题,仔细看了第一题题目,在一个多小时的时候(画外音,此时没有一个人AC题目,说明这次比赛确实很难,不是我水平太挫……虽然是很挫……)突然发现第一题原来很简单(事后发现我想错了),先判断每一个点能否跟第一个点连,再判断能否跟最后一个点连,能的话就想办法输出结果。判断当然是用的并查集,于是乎就写并查集,写得不亦乐乎,然后并查集写完了准备写输出,发现想错了……前面全部白写……(画外音,这时候大概时间是2小时不到点,好像有一个人AC了C题,另外就没人AC题目了,情况就是大家都是0分……基本确定不出意外的话做出题目的人不会太多,只要过了一道题目,即使是A的50分也能过!)调整了一下情绪,重新审视了一下题目,仔细想了一下题意,想出一个算法,大概思路是初始状况是一个只有两个点的链表,起点和终点分别是给定的点。之后从起点开始找路径,规则是无环,终点是已经在答案列表里面的任意一个点(初始的时候只有起点和终点),找到之后把找到的路径除了起点之外所有的点都插到找到的路径的终点的前面,作为答案的一部分。把答案的第一个点能够满足条件的都找过之后就从第二个点开始找,停止条件是找到最后一个点或者所有点都已经在答案里面。看起来复杂度挺高,实际上仔细分析复杂度是比较低的~~提交,发现WA,改,WA,改,WA……悲剧中……(画外音,这时候大概两个多小时好像,只有两个人AC了C,其他都没人AC,而且两个人之中有一个是临时账号……没有参赛资格那种……所以说情况其实还不错),然后这时候发现规则居然改了……改成按数据点给分,而且第一题前一部分数据变成99分(出现了大量45分党,直接输出NO……),马上提交,15分,大悲剧……总分99分话说……于是乎就找啊找的……改了一些细节错误,到了40多分,继续改啊改……发现用vector保存边,一开始是开一个MAXN的vector数组,然后直接构造函数+析构函数的时间就几乎超时了……改成指针动态创建……节约大量时间,然后又改了一些错误,发现结果是93分,看了一下,居然没有人过A,最高就都是93分,说明可能题目有问题……(画外音,大概三个多小时的时候吧,时间改了……延长一个小时,而且B和C也按数据给分),于是准备看看C能不能骗点分到。

一开始想到了个贪心的办法,于是写高精度,写到11点不到点,这时候发现有人过了A了!于是重新提交了一下A,发现居然AC了……看来改数据了……悲剧……发现写高精度不是办法……速度太慢了……正负处理起来太麻烦了……干脆放弃高精度,直接long double骗分!(仿佛回到了NOIP……我想起了骗分导论……,画外音,这时候大概有50人AC了A,晋级应该问题不大了)写了个贪心,发现样例都过不了,想了下,又重新改了一下,终于把样例过了……于是不解释,提交,WA,意料之中,具体分数要rejudge之后才知道了,最后时刻,看了一下B,写了个直接输出\N的程序,运气好能骗到分的说……基本上比赛时间差不多了,吃了点东西压压惊,比赛结束之后,总共事实上AC了题目的有90人,有几个是AC了C的,大部分是A拿了99分,晋级应该问题不大,小台灯,我来了

阅读全文

POJ1042

先上题目……

Gone Fishing

**Time Limit:** 2000MS **Memory Limit:** 32768K
**Total Submissions:** 15920 **Accepted:** 4444

Description

John is going on a fishing trip. He has h hours available (1 <= h <= 16), and there are n lakes in the area (2 <= n <= 25) all reachable along a single, one-way road. John starts at lake 1, but he can finish at any lake he wants. He can only travel from one lake to the next one, but he does not have to stop at any lake unless he wishes to. For each i = 1,…,n - 1, the number of 5-minute intervals it takes to travel from lake i to lake i + 1 is denoted ti (0 < ti <=192). For example, t3 = 4 means that it takes 20 minutes to travel from lake 3 to lake 4. To help plan his fishing trip, John has gathered some information about the lakes. For each lake i, the number of fish expected to be caught in the initial 5 minutes, denoted fi( fi >= 0 ), is known. Each 5 minutes of fishing decreases the number of fish expected to be caught in the next 5-minute interval by a constant rate of di (di >= 0). If the number of fish expected to be caught in an interval is less than or equal to di , there will be no more fish left in the lake in the next interval. To simplify the planning, John assumes that no one else will be fishing at the lakes to affect the number of fish he expects to catch.

Write a program to help John plan his fishing trip to maximize the number of fish expected to be caught. The number of minutes spent at each lake must be a multiple of 5.

Input

You will be given a number of cases in the input. Each case starts with a line containing n. This is followed by a line containing h. Next, there is a line of n integers specifying fi (1 <= i <=n), then a line of n integers di (1 <=i <=n), and finally, a line of n - 1 integers ti (1 <=i <=n - 1). Input is terminated by a case in which n = 0.

Output

For each test case, print the number of minutes spent at each lake, separated by commas, for the plan achieving the maximum number of fish expected to be caught (you should print the entire plan on one line even if it exceeds 80 characters). This is followed by a line containing the number of fish expected.

If multiple plans exist, choose the one that spends as long as possible at lake 1, even if no fish are expected to be caught in some intervals. If there is still a tie, choose the one that spends as long as possible at lake 2, and so on. Insert a blank line between cases.

Sample Input

2 <br></br>1 <br></br>10 1 <br></br>2 5 <br></br>2 <br></br>4 <br></br>4 <br></br>10 15 20 17 <br></br>0 3 4 3 <br></br>1 2 3 <br></br>4 <br></br>4 <br></br>10 15 50 30 <br></br>0 3 4 3 <br></br>1 2 3 <br></br>0 

Sample Output

45, 5 <br></br>Number of fish expected: 31 <br></br><br></br>240, 0, 0, 0 <br></br>Number of fish expected: 480 <br></br><br></br>115, 10, 50, 35 <br></br>Number of fish expected: 724 <br></br><br></br>本来以为这道题目不用写日志了的……最后发现还是很悲剧的一个题目……看了Discuss里面的数据才过……<br></br>本身这道题目意思还算简单,也就是一个不难的DP,外加需要输出结果……<br></br>从DP的角度来讲真是没什么好说的……至于输出结果只要状态转移的时候记录一下就OK了……<br></br>犯了不少错误,最开始写程序的时候就没想清楚就开始写,然后导致的结果是DP的两个维位置不符合思维定势,然后很累……<br></br>另外在测试样例的时候最后一个数据老是不对,然后就以为是顺序不对,最后居然发现是在输出结果的时候递归出问题……<br></br>还有个问题就是记录前一位的时候对于在第一个湖呆了很久的那种情况处理出了点问题……各种悲剧……<br></br>总体来看原因就是做题目的时候思路还不够清晰就开始写写程序了,根据经验来看这是大忌……老是因为这样子出问题……要把这个坏习惯改掉……<br></br>另外手感确实下降了……怎么说这道DP真的挺水的话说……思路不够清晰……比赛的时候遇到这么个东西轻则损失一道题目,重则浪费大量时间啊……必须克服掉……<br></br>
阅读全文

POJ1041

John’s trip

**Time Limit:** 1000MS **Memory Limit:** 65536K
**Total Submissions:** 3223 **Accepted:** 952 Special Judge

Description

Little Johnny has got a new car. He decided to drive around the town to visit his friends. Johnny wanted to visit all his friends, but there was many of them. In each street he had one friend. He started thinking how to make his trip as short as possible. Very soon he realized that the best way to do it was to travel through each street of town only once. Naturally, he wanted to finish his trip at the same place he started, at his parents’ house.

The streets in Johnny’s town were named by integer numbers from 1 to n, n < 1995. The junctions were independently named by integer numbers from 1 to m, m <= 44. No junction connects more than 44 streets. All junctions in the town had different numbers. Each street was connecting exactly two junctions. No two streets in the town had the same number. He immediately started to plan his round trip. If there was more than one such round trip, he would have chosen the one which, when written down as a sequence of street numbers is lexicographically the smallest. But Johnny was not able to find even one such round trip.

Help Johnny and write a program which finds the desired shortest round trip. If the round trip does not exist the program should write a message. Assume that Johnny lives at the junction ending the street appears first in the input with smaller number. All streets in the town are two way. There exists a way from each street to another street in the town. The streets in the town are very narrow and there is no possibility to turn back the car once he is in the street

Input

Input file consists of several blocks. Each block describes one town. Each line in the block contains three integers x; y; z, where x > 0 and y

0 are the numbers of junctions which are connected by the street number z. The end of the block is marked by the line containing x = y =

  1. At the end of the input file there is an empty block, x = y = 0.

Output

Output one line of each block contains the sequence of street numbers (single members of the sequence are separated by space) describing Johnny’s round trip. If the round trip cannot be found the corresponding output block contains the message “Round trip does not exist.”

Sample Input

1 2 1<br></br>2 3 2<br></br>3 1 6<br></br>1 2 5<br></br>2 3 3<br></br>3 1 4<br></br>0 0<br></br>1 2 1<br></br>2 3 2<br></br>1 3 3<br></br>2 4 4<br></br>0 0<br></br>0 0

Sample Output

1 2 3 5 4 6 <br></br>Round trip does not exist.<br></br><span style="font-family: Arial;"><br></br>最近几天基本都没做题目……<br></br>这题目那天看了感觉是欧拉回路,判断还好说,输出一条字典序最小的路感觉有点麻烦。搜索了一下输出欧拉回路的方法,发现基本思想是先找一条回路,然后在找到的回路中以度不为0的点为起点继续找回路,插入到一开始找到的回路中。直到所有边都被枚举。<br></br>看了这个思路感觉想不出什么方便的办法……开两个过程一个递归,然后另外一个再处理插入啥的……为了减小复杂度还用到链表……各种麻烦……<br></br>百度里面的算法很简单,一开始一直没看懂,后来突然一下懂了,先枚举的点放在后面,之后倒序输出,相当棒的算法……而且貌似曾经我知道这玩意儿……而且根据这个算法只要循环的时候枚举边就自动输出字典序……题目还是比较简单的居然……<br></br>贴代码……<br></br>#include <stdio.h><br></br>#include <string.h><br></br>#include <list><br></br><br></br>using namespace std;<br></br><br></br>typedef list<int> listInt;<br></br>listInt ans;<br></br><br></br>int n = 2000, m = 45;<br></br>int t;<br></br>int street[2010][3];<br></br>int match[2010];<br></br><br></br>int start;<br></br><br></br>bool Init()<br></br>{<br></br>int x, y, z, tmp;<br></br>memset(street, 0, sizeof(street));<br></br>memset(match, 0, sizeof(match));<br></br>ans.clear();<br></br>scanf("%d%d", &x, &y);<br></br>if(x == 0 && y == 0)<br></br>return false;<br></br>start = x;<br></br>if(start > y)<br></br>start = y;<br></br>while(x != 0){<br></br>scanf("%d", &z);<br></br>if(x > y){<br></br>tmp = x;<br></br>x = y;<br></br>y = tmp;<br></br>}<br></br>match[x]++;<br></br>match[y]++;<br></br>street[z][0] = x;<br></br>street[z][1] = y;<br></br>scanf("%d%d", &x, &y);<br></br>}<br></br>return true;<br></br>}<br></br><br></br>int father[50];<br></br><br></br>int GetFar(int k)<br></br>{<br></br>if(father[k] == k)<br></br>return k;<br></br>else{<br></br>father[k] = GetFar(father[k]);<br></br>return father[k];<br></br>}<br></br>}<br></br><br></br>bool Check()<br></br>{<br></br>for(int i=0; i<=m; i++)<br></br>father[i] = i;<br></br>for(int i=1; i<=n; i++){<br></br>if(street[i][0] != 0 && street[i][1] != 0){<br></br>father[GetFar(street[i][0])] = GetFar(street[i][1]);<br></br>}<br></br>}<br></br>for(int i=1; i<=n; i++){<br></br>if(match[i] == 0)<br></br>continue;<br></br>if(match[i] % 2 == 1)<br></br>return false;<br></br>if(GetFar(i) != GetFar(start))<br></br>return false;<br></br>}<br></br>return true;<br></br>}<br></br><br></br>void Euler(int start)<br></br>{<br></br>if(match[start] > 0){<br></br>for(int i=1; i<=n; i++){<br></br>if(street[i][2] == 0 &&(street[i][0] == start || street[i][1] == start)){<br></br>street[i][2] = 1;<br></br>match[street[i][0]] --;<br></br>match[street[i][1]] --;<br></br>if(street[i][0] == start){<br></br>Euler(street[i][1]);<br></br>}else if(street[i][1] == start){<br></br>Euler(street[i][0]);<br></br>}<br></br>ans.push_back(i);<br></br>}<br></br>}<br></br>}<br></br>}<br></br><br></br>void Solve()<br></br>{<br></br>if(!Check()){<br></br>printf("Round trip does not exist.\n");<br></br>return ;<br></br>}<br></br>t = 0;<br></br>Euler(start);<br></br><br></br>for(listInt::const_reverse_iterator i = ans.rbegin(); i != ans.rend(); ++i){<br></br>if(i != ans.rbegin()){<br></br>printf(" ");<br></br>}<br></br>printf("%d", *i);<br></br>}<br></br>printf("\n");<br></br>}<br></br><br></br>int main()<br></br>{<br></br>while(Init()){<br></br>Solve();<br></br>}<br></br>}<br></br><br></br><br></br></span>
阅读全文

POJ1039

POJ1039,又一道计算几何,又一道悲剧……

先上题目……

Pipe

**Time Limit:** 1000MS **Memory Limit:** 10000K
**Total Submissions:** 3692 **Accepted:** 1117

Description

The GX Light Pipeline Company started to prepare bent pipes for the new transgalactic light pipeline. During the design phase of the new pipe shape the company ran into the problem of determining how far the light can reach inside each component of the pipe. Note that the material which the pipe is made from is not transparent and not light reflecting.

Each pipe component consists of many straight pipes connected tightly together. For the programming purposes, the company developed the description of each component as a sequence of points [x1; y1], [x2; y2], . . ., [xn; yn], where x1 < x2 < . . . xn . These are the upper points of the pipe contour. The bottom points of the pipe contour consist of points with y-coordinate decreased by 1. To each upper point [xi; yi] there is a corresponding bottom point [xi; (yi)-1] (see picture above). The company wants to find, for each pipe component, the point with maximal x-coordinate that the light will reach. The light is emitted by a segment source with endpoints [x1; (y1)-1] and [x1; y1] (endpoints are emitting light too). Assume that the light is not bent at the pipe bent points and the bent points do not stop the light beam.

Input

The input file contains several blocks each describing one pipe component. Each block starts with the number of bent points 2 <= n <= 20 on separate line. Each of the next n lines contains a pair of real values xi, yi separated by space. The last block is denoted with n = 0.

Output

The output file contains lines corresponding to blocks in input file. To each block in the input file there is one line in the output file. Each such line contains either a real value, written with precision of two decimal places, or the message Through all the pipe.. The real value is the desired maximal x-coordinate of the point where the light can reach from the source for corresponding pipe component. If this value equals to xn, then the message Through all the pipe. will appear in the output file.

Sample Input

4<br></br>0 1<br></br>2 2<br></br>4 1<br></br>6 4<br></br>6<br></br>0 1<br></br>2 -0.6<br></br>5 -4.45<br></br>7 -5.57<br></br>12 -10.8<br></br>17 -16.55<br></br>0<br></br>

Sample Output

4.67<br></br>Through all the pipe.<br></br>很久没做题目了……2个礼拜前其实就看到了,昨晚决定把这题目过了先。<br></br>题目意思是有一大堆管子,从管口有一个线光源,然后问你光源最大能够到达的点的x坐标……<br></br>话说一开始一直以为是距离……而且天杀的样例数据居然还能对……<br></br>那天看了计算几何的一些东西,里面提到最烦的3种题目……格式输出,模拟还有计算几何……感觉很有道理……<br></br>计算几何之所以烦,一方面是很多直观的东西到了计算机里面反而很麻烦……不过如果有现成的算法其实倒也不是很麻烦,最烦的地方在于计算几何的特殊情况太恶心了。<br></br>比如想要表示一条直线,因为可能垂直或者平行,所以只能用标准式,不能用点斜式……然后求线段相交的情况就有是否在某个端点相交,是否恰好共端点……还有重合……疯了疯了……<br></br>如果只是函数里面考虑这些东西还好,有模板抄,万恶的是题目里面还要考虑这种特殊情况,然后……疯了疯了<br></br>突然发现,我做过的几道计算几何的题目都是要考虑这种东西的……或者说是我想到的算法都是要考虑这种东西的……然后每次到最后我都是用牺牲一些精度来获取答案……不知道是不是好事……<br></br>拿这道题目来说吧,我的算法是枚举每两个端点对,对于符合条件的直线,肯定通过某两个端点……直观的想想是这样子的……<br></br>然后过这两个端点做直线,测试是否与入口的线光源相交,如果相交就从交点出发,做一条射线(光线),之后枚举每一条边,看是否相交,如果有相交就取交点最小的x值,如果没有就是可以通过所有管子。<br></br>具体实现的时候有一种很恶心的情况,在内部的时候,某个交点是不会把光线挡住的,这样子其实还不麻烦,但是问题是就可能出现光线从相交的地方出去了……然后分情况考虑又恶心的要死……<br></br>最后我就在判断相交的时候把每一条上面的变往上移一个eps,每一条下面的边往下移一个eps……然后就不用考虑了……牺牲了一点点精度……<br></br>贴代码……<br></br>#include <cstdio><br></br>#include <cmath><br></br><br></br>using namespace std;<br></br><br></br>const double eps = 1e-9;<br></br><br></br>struct POINT  <br></br>{<br></br>double x, y;<br></br>POINT(){<br></br>x = y = 0;<br></br>}<br></br>POINT(double xx, double yy){<br></br>x = xx;y=yy;<br></br>}<br></br>};<br></br><br></br>struct LINESEG<br></br>{<br></br>POINT p1, p2;<br></br>LINESEG(){<br></br><br></br>}<br></br>LINESEG(POINT pp1, POINT pp2){<br></br>p1 = pp1;p2 = pp2;<br></br>}<br></br>};<br></br><br></br>struct LINE<br></br>{<br></br>double a, b, c;<br></br>};<br></br><br></br>double Multiply(POINT sp,POINT ep,POINT op)<br></br>{<br></br>return((sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x));<br></br>}<br></br><br></br>double max(double a, double b)<br></br>{<br></br>return a>b?a:b;<br></br>}<br></br><br></br>double min(double a, double b)<br></br>{<br></br>return a<b?a:b;<br></br>}<br></br><br></br><br></br>LINE MakeLine(POINT p1, POINT p2)<br></br>{<br></br>LINE tl;<br></br>int sign = 1;<br></br>tl.a = p2.y - p1.y;<br></br>if(tl.a < 0){<br></br>sign = -1;<br></br>tl.a = sign*tl.a;<br></br>}<br></br>tl.b = sign*(p1.x - p2.x);<br></br>tl.c = sign*(p1.y*p2.x - p1.x*p2.y);<br></br>return tl;<br></br>}<br></br><br></br>LINE MakeLine(LINESEG l)<br></br>{<br></br>return MakeLine(l.p1, l.p2);<br></br>}<br></br><br></br>bool Lineintersect(LINE l1, LINE l2, POINT &p)<br></br>{<br></br>double d = l1.a*l2.b - l2.a*l1.b;<br></br>if(abs(d) < eps)<br></br>return false;<br></br>p.x = (l2.c*l1.b-l1.c*l2.b)/d;<br></br>p.y = (l2.a*l1.c - l1.a*l2.c)/d;<br></br>return true;<br></br>}<br></br><br></br>bool Intersect(LINESEG l1, LINESEG l2, POINT &pInterSect)<br></br>{<br></br>if ((max(l1.p1.x, l1.p2.x) > min(l2.p1.x, l2.p2.x))&&//快速排斥实验<br></br>(max(l1.p1.y, l1.p2.y) > min(l2.p1.y, l2.p2.y))&&<br></br>(max(l2.p1.x, l2.p2.x) > min(l1.p1.x, l1.p2.x))&&<br></br>(max(l2.p1.y, l2.p2.y) > min(l1.p1.y, l1.p2.y))&&<br></br>(Multiply(l1.p1, l2.p1, l2.p2)*Multiply(l1.p2, l2.p1, l2.p2) <= 0)&&//跨立实验<br></br>(Multiply(l2.p1, l1.p1, l1.p2)*Multiply(l2.p2, l1.p1, l1.p2) <= 0)){<br></br>Lineintersect(MakeLine(l1.p1, l1.p2), MakeLine(l2.p1, l2.p2), pInterSect);<br></br>return true;<br></br>}else{<br></br>return false;<br></br>}<br></br>}<br></br><br></br>bool online(LINESEG l,POINT p) <br></br>{ <br></br>return( (Multiply(l.p2,p,l.p1)==0) &&( ( (p.x-l.p1.x)*(p.x-l.p2.x)<=0 )&&( (p.y-l.p1.y)*(p.y-l.p2.y)<=0 ) ) ); <br></br>} <br></br><br></br>bool Intersect_A(LINESEG u,LINESEG v, POINT p) <br></br>{ <br></br>if((Intersect(u,v, p))&& <br></br>(!online(u,v.p1))&& <br></br>(!online(u,v.p2))&& <br></br>(!online(v,u.p1))&& <br></br>(!online(v,u.p2))){<br></br>Intersect(u, v, p);<br></br>return true;<br></br>} <br></br>else{<br></br>return false;<br></br>}<br></br>} <br></br><br></br>LINESEG MakeSeg(POINT p1, POINT p2, int flag)//flag为0,1,2,3时分别不扩展,扩展p1到p2方向,扩展p2到p1方向,都扩展<br></br>{<br></br>LINESEG ret;<br></br>ret.p1 = p1;<br></br>ret.p2 = p2;<br></br>double d = 0;<br></br>if(p1.x - p2.x != 0)<br></br>d = abs(1e6/(p1.x-p2.x));<br></br>if(d == 0 && (p1.y - p2.y != 0))<br></br>d = abs(1e6/(p1.y-p2.y));<br></br>if(flag & 1){<br></br>ret.p2.x += (p2.x-p1.x)*d;<br></br>ret.p2.y += (p2.y-p1.y)*d;<br></br>}<br></br>if(flag & 2){<br></br>ret.p1.x += (p1.x-p2.x)*d;<br></br>ret.p1.y += (p1.y-p2.y)*d;<br></br>}<br></br>return ret;<br></br>}<br></br><br></br>double sqr(double a)<br></br>{<br></br>return a*a;<br></br>}<br></br><br></br>double Distance(POINT p1, POINT p2)<br></br>{<br></br>return sqrt(sqr(p1.x-p2.x)+sqr(p2.y-p2.y));<br></br>}<br></br><br></br>POINT p[50];<br></br>int n;<br></br><br></br>void Init()<br></br>{<br></br>for (int i=1; i<=n; i++){<br></br>scanf("%lf%lf", &p[i].x, &p[i].y);<br></br>}<br></br>for (int i=n+1; i<=2*n; i++){<br></br>p[i] = p[i-n];<br></br>p[i].y -= 1;<br></br>}<br></br>}<br></br><br></br>double Check(LINESEG ray)<br></br>{<br></br>double ret = 1e6;<br></br>POINT pIntersect;<br></br>for(int i=1; i<=n-1; i++){<br></br>LINESEG l(p[i], p[i+1]);<br></br>l.p1.y += eps;<br></br>l.p2.y += eps;<br></br>if(Intersect(ray, l, pIntersect)){<br></br>ret = min(ret, pIntersect.x);<br></br>}<br></br>l.p1.y -= 1+2*eps;<br></br>l.p2.y -= 1+2*eps;<br></br>if(Intersect(ray, l, pIntersect)){<br></br>ret = min(ret, pIntersect.x);<br></br>}<br></br>}<br></br>return ret;<br></br>}<br></br><br></br>void Solve()<br></br>{<br></br>int i, j, k;<br></br>LINESEG ray;<br></br>double ans;<br></br>ans = -1e10;<br></br>LINESEG lTest;<br></br>lTest.p1 = p[1];<br></br>lTest.p2 = p[n+1];<br></br>lTest.p1.y += eps;<br></br>lTest.p2.y -= eps;<br></br>for(i=1; i<=2*n; i++)<br></br>for(j=i+1; j<=2*n; j++){<br></br>ray = MakeSeg(p[i], p[j], 3);<br></br>if(!Intersect(lTest, ray, p[0]))<br></br>continue;<br></br>ray = MakeSeg(p[0], p[j], 1);<br></br>if(abs(p[0].x - p[j].x)<eps){<br></br>if(abs(p[0].x - p[i].x)<eps)<br></br>continue;<br></br>ray = MakeSeg(p[0], p[i], 1);<br></br>}<br></br>double ret = Check(ray);<br></br>if(ret > ans)<br></br>ans = ret;<br></br>if(ans == 1e6){<br></br>printf("Through all the pipe.\n");<br></br>return ;<br></br>}<br></br>}<br></br>printf("%.2f\n", ans);<br></br>}<br></br><br></br>int main()<br></br>{<br></br>while(true){<br></br>scanf("%d", &n);<br></br>if(n <= 0)<br></br>break;<br></br>Init();<br></br>Solve();<br></br>}<br></br>return 0;<br></br>}<br></br><br></br>代码里面有很多函数没用到,主要是程序前后改了很多次……计算几何用到的那些函数都是抄的模板。<br></br>
阅读全文

泰国的奥特曼……自带避雷针,硬化氪金狗眼

承受力比较强的可以直接拖到5分钟的地方……

阅读全文

记我可怜的游戏分区……

.

记得刚买本的时候看着250G的硬盘还是有小鸡动啊……以前的台式机是40G,一下子变成6倍多了……然后规划分区,貌似当时规划了10的XP的C盘,20GVista的D盘,然后游戏盘100G,软件盘30G,剩下的作为数据盘,各种乱七八糟的数据。

然后Win7的beta阶段用了Win7,感觉相当不错,就直接把XP和Win7的分区重新分成了20G+10G,Win7在前……搞定之后坚持了一段时间……突然想用Linux了……于是把XP给废了……慢慢游戏没玩了……G盘里面各种东西越来越多,然后又舍不得删,E盘的游戏一直很空……换了几次不同的发行版的Linux,感觉10G太少了……Win7的20G也有点吃力……于是把20和10合并了……30G放Win7,然后游戏盘剥削出20G,放Linux……

然后又发现G盘的代码占了很多空间……然后E盘前面空着个D盘很不爽……干脆又剥削了20G出来,专门放代码……

再然后G盘一直飘红……实在不爽……看着AFK了1年多了的WOW……直接删了,空出10多G空间,再删点其他乱七八糟的东西,然后把G盘里面的ISO整体搬迁到E盘……G盘清净了……我可怜的游戏盘悲剧了……谨以此作为纪念吧……可怜的E盘……

不知道为什么,特别喜欢E盘这个符号作为游戏盘,可能是因为那会儿40G里面是E盘是最后一个分区吧……当时没啥分区概念……东西都放在C和E,D一直空的……悲剧……后来慢慢知道了……但是D就一直是个悲剧……E就一直是游戏……

阅读全文

POJ1038,终于过了……

POJ1038……断断续续做了4天……本身由于这段时间有点事情,时间不太多,再加上这题目确实比较麻烦……

Bugs Integrated, Inc.

**Time Limit:** 15000MS **Memory Limit:** 30000K
**Total Submissions:** 4660 **Accepted:** 1641
**Case Time Limit:** 5000MS

Description

Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launching production of a new six terabyte Q-RAM chip. Each chip consists of six unit squares arranged in a form of a 23 rectangle. The way Q-RAM chips are made is such that one takes a rectangular plate of silicon divided into NM unit squares. Then all squares are tested carefully and the bad ones are marked with a black marker.

Finally, the plate of silicon is cut into memory chips. Each chip consists of 23 (or 32) unit squares. Of course, no chip can contain any bad (marked) squares. It might not be possible to cut the plate so that every good unit square is a part of some memory chip. The corporation wants to waste as little good squares as possible. Therefore they would like to know how to cut the plate to make the maximum number of chips possible.

Task

You are given the dimensions of several silicon plates and a list of all bad unit squares for each plate. Your task is to write a program that computes for each plate the maximum number of chips that can be cut out of the plate.

Input

The first line of the input file consists of a single integer D (1 <= D <= 5), denoting the number of silicon plates. D blocks follow, each describing one silicon plate. The first line of each block contains three integers N (1 <= N <= 150), M (1 <= M <= 10), K (0 <= K <= MN) separated by single spaces. N is the length of the plate, M is its height and K is the number of bad squares in the plate. The following K lines contain a list of bad squares. Each line consists of two integers x and y (1 <= x <= N, 1 <= y <= M) ?coordinates of one bad square (the upper left square has coordinates [1, 1], the bottom right is [N,M]).

Output

For each plate in the input file output a single line containing the maximum number of memory chips that can be cut out of the plate.

Sample Input

2<br></br>6 6 5<br></br>1 4<br></br>4 6<br></br>2 2<br></br>3 6<br></br>6 4<br></br>6 5 4<br></br>3 3<br></br>6 1<br></br>6 2<br></br>6 4<br></br>

Sample Output

3<br></br>4<br></br><br></br>还记得刚看到题目的时候,一开始想到的是DFS……因为点不太多,但是发现找不到一个好的搜索策略……虽然注意到M<=10,但是想不到怎么利用,又想可能是DP,但是想不到怎么DP……状态都没想到……<br></br>想了一个晚上竟然……最后放弃,看了Discuss,看到标题大都是DP,三进制啥的……原来是一道状态压缩的DP……话说其实也不是第一次作状态压缩的题目了……于是继续想DP的办法……想了半天还是很混乱……然后我贸然就写代码了……在没有想清楚状态转移方程的情况下……Sample都过不了……<br></br>最后决定baidu一下别人的代码……看了别人的一些报告和代码……发现状态转移居然用的DFS……以前都没遇到过这种题目……第一次遇到……题目做的还是少阿……<br></br>话说知道了是DFS,我竟然还是想不到具体怎么DFS……想到一些比较朴素的方法,但是感觉速度会很慢……<br></br>继续看代码……看到一个写得很装B的代码(为什么说装B呢……因为代码很短,而且作者刻意地想要让自己的代码显得短),60行的样子……居然可以……不过话说回来……虽说装B,不过这种状态转移的办法确实很不错……要是我的话绝对想不到……附上地址:http://read.pudn.com/downloads81/sourcecode/others/312921/poj1038%E5%91%A8%E4%BC%9F.cpp__.htm<br></br>除了这种强悍的,也有一些方法相对朴素的,就是在DFS的时候传递一个数组,每次进行编码。<br></br>我按照朴素的写了一个出来,DEBUG了一些小错误之后AC了,速度出乎意料的快,居然只用了650多MS……排第9……神奇了……不过第一的那个只用了110MS……又按照那个很巧妙的办法改写了一下dfs重新写了一个,提交之后花了2000多MS……悲剧……代码短不一定速度快阿……<br></br>说一下思路吧……这题目确实挺不错的……<br></br><br></br>最基本的思想就是状态压缩,对于到达某1列的时候,用3进制表示它右边的两行的状态,0,1,2分别表示右边两个都空,占用1个与占用两个。<br></br>然后就能DP了……由于内存限制……另外DP的时候只跟前一列有关系,所以可以用滚动数组。<br></br>具体在写的时候有个比较实用的预处理。<br></br>记录某个点不能使用的时候不是记录点坐标,而是开两个数组,对于每一个不能使用的点,把由于这个点而不能摆放的长方形都找出来,然后标记一下,这样到DP的时候能够少打不少字……<br></br>然后状态转移的方法刚刚提到了,是DFS。有两种策略,先说我用的策略,朴素,但是实际结果下来速度反而快。<br></br>对于每一列的每一个状态,把状态解码放到一个数组里面,进行DFS,相当于把每个状态能够推出来的所有状态都DFS出来。具体作的时候由于牵扯到数组了,感觉会比较慢……实际反而快……不知为何……<br></br>另外一种方法,感觉很巧妙,直接对于每一列进行一次DFS,DFS的时候带两个状态参数,分别表示此列状态和上一列状态,然后求出所有能够从p2推到p1的状态对……哎……感觉说不清楚……直接附上代码……<br></br>方法1:<br></br>#include <stdio.h><br></br>#include <string.h><br></br><br></br>#define MAX 59049<br></br><br></br>short a[2][MAX];<br></br>bool CouldH[155][11], CouldV[155][11];<br></br>int n, m, nBad;<br></br>int power[11];<br></br><br></br>void Init()<br></br>{<br></br>    int i;<br></br>    power[0] = 1;<br></br>    for(i=1; i<=10; i++){<br></br>        power[i] = power[i-1]*3;<br></br>    }<br></br>}<br></br>void InitCase()<br></br>{<br></br>    memset(a, 0, sizeof(a));<br></br>    memset(CouldH, true, sizeof(CouldH));<br></br>    memset(CouldV, true, sizeof(CouldV));<br></br>    scanf("%d%d%d", &n, &m, &nBad);<br></br>    int i, j, x, y;<br></br>    while(nBad --){<br></br>        scanf("%d%d", &x, &y);<br></br>        for(i=-2; i<=0; i++)<br></br>            for(j=-1; j<=0; j++){<br></br>                if(x+i >= 0 && y+j > 0)<br></br>                    CouldH[x+i][y+j-1] = false;<br></br>                if(x+j >= 0 && y+i > 0)<br></br>                    CouldV[x+j][y+i-1] = false;<br></br>            }<br></br>    }<br></br>    for(i=0; i<=n; i++){<br></br>        CouldH[i][m-1] = false;<br></br>        CouldV[i][m-1]=CouldV[i][m-2] = false;<br></br>    }<br></br>    for(i=0; i<m; i++){<br></br>        CouldH[n][i] = CouldH[n-1][i] = false;<br></br>        CouldV[n][i] = false;<br></br>    }<br></br>}<br></br><br></br>int CodeMinus(int a[11]){<br></br>    int ret = 0, i;<br></br>    for(i=0; i<m; i++)<br></br>        if(a[i] > 0)<br></br>            ret += (a[i]-1)*power[i];<br></br>    return ret;<br></br>}<br></br><br></br>void Decode(int k, int status[11])<br></br>{<br></br>    for(int i=0; i<m; i++){<br></br>        status[i] = k%3;<br></br>        k = k/3;<br></br>    }<br></br>}<br></br><br></br>void dfs(int i, int j, int status[11], int cnt)<br></br>{<br></br>    if(j >= m){<br></br>        int code = CodeMinus(status);<br></br>        if(a[i%2][code] < cnt)<br></br>            a[i%2][code] = cnt;<br></br>        return ;<br></br>    }<br></br>    if(CouldH[i][j] && status[j] == 0 && status[j+1] == 0){<br></br>        status[j] = status[j+1] = 3;<br></br>        dfs(i, j+2, status, cnt+1);<br></br>        status[j] = status[j+1] = 0;<br></br>    }<br></br>    if(CouldV[i][j] && status[j] == 0 && status[j+1] == 0 && status[j+2] == 0){<br></br>        status[j] = status[j+1] = status[j+2] = 2;<br></br>        dfs(i, j+3, status, cnt+1);<br></br>        status[j] = status[j+1] = status[j+2] = 0;<br></br>    }<br></br>    dfs(i, j+1, status, cnt);<br></br>}<br></br><br></br>void Solve()<br></br>{<br></br>    int now, i, j, status[11];<br></br> 
;   memset(a[0], 0xff, sizeof(a[1]));<br></br>a[0][0] = 0;<br></br>    for(i=1; i<=n; i++){<br></br>        now = i%2;<br></br>        memset(a[now], 0xff, sizeof(a[now]));<br></br>        for(j=0; j< power<p align="center" fromubb="1">­; j++){<br></br>            if(a[1-now][j] < 0)<br></br>                continue;<br></br>            Decode(j, status);<br></br>            dfs(i, 0, status, a[1-now][j]);<br></br>        }<br></br>        <br></br>    }<br></br>    int ans = 0;<br></br>    for(i=0; i < power<p align="center" fromubb="1">­; i++){<br></br>        if(ans < a[n%2][i])<br></br>            ans = a[n%2][i];<br></br>    }<br></br>    printf("%d\n", ans);<br></br>}<br></br><br></br>int main()<br></br>{<br></br>    int nCase;<br></br>    scanf("%d", &nCase);<br></br>    Init();<br></br>    while(nCase--){<br></br>        InitCase();<br></br>        Solve();<br></br>    }<br></br>    return 0;<br></br>}<br></br>方法2:<br></br>#include <stdio.h><br></br>#include <string.h><br></br><br></br>#define MAX 59049<br></br><br></br>short a[2][MAX];<br></br>bool CouldH[155][11], CouldV[155][11];<br></br>int n, m, nBad;<br></br>int power[11];<br></br><br></br>void Init()<br></br>{<br></br>    int i;<br></br>    power[0] = 1;<br></br>    for(i=1; i<=10; i++){<br></br>        power[i] = power[i-1]*3;<br></br>    }<br></br>}<br></br>void InitCase()<br></br>{<br></br>    memset(a, 0, sizeof(a));<br></br>    memset(CouldH, true, sizeof(CouldH));<br></br>    memset(CouldV, true, sizeof(CouldV));<br></br>    scanf("%d%d%d", &n, &m, &nBad);<br></br>    int i, j, x, y;<br></br>    while(nBad --){<br></br>        scanf("%d%d", &x, &y);<br></br>        for(i=-2; i<=0; i++)<br></br>            for(j=-1; j<=0; j++){<br></br>                if(x+i >= 0 && y+j > 0)<br></br>                    CouldH[x+i][y+j-1] = false;<br></br>                if(x+j >= 0 && y+i > 0)<br></br>                    CouldV[x+j][y+i-1] = false;<br></br>            }<br></br>    }<br></br>    for(i=0; i<=n; i++){<br></br>        CouldH[i][m-1] = false;<br></br>        CouldV[i][m-1]=CouldV[i][m-2] = false;<br></br>    }<br></br>    for(i=0; i<m; i++){<br></br>        CouldH[n][i] = CouldH[n-1][i] = false;<br></br>        CouldV[n][i] = false;<br></br>    }<br></br>}<br></br><br></br>void dfs(int i, int j, int p1, int p2, int cnt)<br></br>{<br></br>    if(j >= m){<br></br>        if(a[i%2][p1] < a[1-i%2][p2] + cnt)<br></br>            a[i%2][p1] = a[1-i%2][p2]+cnt;<br></br>        return ;<br></br>    }<br></br>    if(CouldH[i][j]){<br></br>        dfs(i, j+2, p1*9+8, p2*9, cnt+1);<br></br>    }<br></br>    if(CouldV[i][j]){<br></br>        dfs(i, j+3, p1*27+13, p2*27, cnt+1);<br></br>    }<br></br>    dfs(i, j+1, p1*3, p2*3+1, cnt);<br></br>    dfs(i, j+1, p1*3+1, p2*3+2, cnt);<br></br>    dfs(i, j+1, p1*3, p2*3, cnt);<br></br>}<br></br><br></br>void Solve()<br></br>{<br></br>    int now, i;<br></br>    memset(a[0], 0xff, sizeof(a[1]));<br></br>    a[0][0] = 0;<br></br>    for(i=1; i<=n; i++){<br></br>        now = i%2;<br></br>        memset(a[now], 0xff, sizeof(a[now]));<br></br>        dfs(i, 0, 0, 0, 0); <br></br>    }<br></br>    int ans = 0;<br></br>    for(i=0; i < power<p align="center" fromubb="1">­; i++){<br></br>        if(ans < a[n%2][i])<br></br>            ans = a[n%2][i];<br></br>    }<br></br>    printf("%d\n", ans);<br></br>}<br></br><br></br>int main()<br></br>{<br></br>    int nCase;<br></br>    scanf("%d", &nCase);<br></br>    Init();<br></br>    while(nCase--){<br></br>        InitCase();<br></br>        Solve();<br></br>    }<br></br>    return 0;<br></br>}<br></br><br></br>
阅读全文

POJ1037……悲剧……

又是挺悲剧的一道题目……上题目先……

Language:Default A decorative fence
**Time Limit:** 1000MS **Memory Limit:** 10000K
**Total Submissions:** 3869 **Accepted:** 1287
Description Richard just finished building his new house. Now the only thing the house misses is a cute little wooden fence. He had no idea how to make a wooden fence, so he decided to order one. Somehow he got his hands on the ACME Fence Catalogue 2002, the ultimate resource on cute little wooden fences. After reading its preface he already knew, what makes a little wooden fence cute. A wooden fence consists of N wooden planks, placed vertically in a row next to each other. A fence looks cute if and only if the following conditions are met: �The planks have different lengths, namely 1, 2, . . . , N plank length units. �Each plank with two neighbors is either larger than each of its neighbors or smaller than each of them. (Note that this makes the top of the fence alternately rise and fall.) It follows, that we may uniquely describe each cute fence with N planks as a permutation a1, . . . , aN of the numbers 1, . . . ,N such that (any i; 1 < i < N) (ai − ai−1)*(ai − ai+1) > 0 and vice versa, each such permutation describes a cute fence. It is obvious, that there are many di erent cute wooden fences made of N planks. To bring some order into their catalogue, the sales manager of ACME decided to order them in the following way: Fence A (represented by the permutation a1, . . . , aN) is in the catalogue before fence B (represented by b1, . . . , bN) if and only if there exists such i, that (any j < i) aj = bj and (ai < bi). (Also to decide, which of the two fences is earlier in the catalogue, take their corresponding permutations, find the first place on which they differ and compare the values on this place.) All the cute fences with N planks are numbered (starting from 1) in the order they appear in the catalogue. This number is called their catalogue number. ![](http://acm.pku.edu.cn/JudgeOnline/images/1037/fence.gif) After carefully examining all the cute little wooden fences, Richard decided to order some of them. For each of them he noted the number of its planks and its catalogue number. Later, as he met his friends, he wanted to show them the fences he ordered, but he lost the catalogue somewhere. The only thing he has got are his notes. Please help him find out, how will his fences look like. Input The first line of the input file contains the number K (1 <= K <= 100) of input data sets. K lines follow, each of them describes one input data set. Each of the following K lines contains two integers N and C (1 <= N <= 20), separated by a space. N is the number of planks in the fence, C is the catalogue number of the fence. You may assume, that the total number of cute little wooden fences with 20 planks fits into a 64-bit signed integer variable (long long in C/C++, int64 in FreePascal). You may also assume that the input is correct, in particular that C is at least 1 and it doesn抰 exceed the number of cute fences with N planks. Output For each input data set output one line, describing the C-th fence with N planks in the catalogue. More precisely, if the fence is described by the permutation a1, . . . , aN, then the corresponding line of the output file should contain the numbers ai (in the correct order), separated by single spaces. Sample Input 2 2 1 3 3 Sample Output 1 2 2 3 1

这道题目意思还是比较容易看懂的,不过做起来比较麻烦……但是我还是自己想到了算法~不过挺悲剧就是……

题目如果只是问总共有多少种方法情况的话能简单不少,直接DP就好了。a[i][j][k]表示总共i个数字第一位是j,k=0表示双数位是大,k=1表示单数位是大的情况个数,然后就能得到DP方程,分K=0,k=1两种情况。具体方程待会儿看源码吧……

然后要打印结果就用递归。一个个减下来。先确定第一位是多少,再递归第二位,再递归第三位。写一个函数getAns(int n, long long c, int j, int k, int ans[]),取总共有n个数,第c种情况,j表示前一位的数值,k表明双数位跟单数位哪个是大,然后结果放在ans里面……最后再处理一下ans就打印了……

呃……突然发现我的算法好复杂……应该有更好的算法……

然后写好程序就提交,发现WA了……悲剧,然后调试,发现一个错误,问题原因是在判断找到确切位置的时候判断条件有问题,数组超下界了……但是没报错……C的悲剧啊……

然后改了,还是WA……话说要上课了……然后就跑去上课了……上课的时候突然想到可能是编译器选了C++的关系,因为用到了long long,于是下课来电阅……换G++,继续WA……大悲剧……然后居然在记事本里面发现了错误……然后错误原因是getAns里面的c不小心用了int……哎……用VIM的大悲剧啊……如果用了IDE的话应该能够发现吧……

话说最后居然在记事本里面就看出了错误所在……说明放下代码一段时间再看代码DEBUG效率高很多啊……比赛的时候善用这点……

贴上代码:

Source Code

**Problem:** [1037](http://acm.pku.edu.cn/JudgeOnline/problem?id=1037) **User:** [dashashi](http://acm.pku.edu.cn/JudgeOnline/userstatus?user_id=dashashi)
**Memory:** 396K **Time:** 32MS
**Language:** G++ **Result:** Accepted
  • Source Code

    #include </span> #include </span>

    int n, t; long long c, a[22][22][2];//a[i][j][k]表示总共i个数字第一位是j, //k=0表示双数位是大,k=1表示单数位是大的情况个数 void Init() { n = 20; int i, j, t; memset(a, 0, sizeof(a)); a[1][1][1] = 1; a[2][2][1] = 1; a[2][1][0] = 1; for(i=3; j<=n; i++) for(j=1; j<=i; j++){ for(t = 1; t<=j-1; t++) a[i][j][1] += a[i-1][t][0]; for(t = j; t<=i; t++) a[i][j][0] += a[i-1][t][1]; } }

    void getAns(int n, long long c, int j, int k, int ans[]) { if(n == 0) return; if(n == 1){ ans[1] = 1; return ; } int t; if(k == 1){ for(t=1; t<=j-1; t++){ if(a[n][t][0] >= c) break; c -= a[n][t][0]; } ans[1] = t; getAns(n-1, c, t, 1-k, ans+1); }else if(k == 0){ for(t=j; t<=n; t++){ if(a[n][t][1] >= c) break; c -= a[n][t][1]; } ans[1] = t; getAns(n-1, c, t, 1-k, ans+1) ; } }

    void print(int n, long long c) { int ans[30], i, j, k; memset(ans, 0, sizeof(ans)); for(j=1; j<=n; j++){ for(k=1; k>=0; k–){ if(a[n][j][k] >= c) break; c -= a[n][j][k]; } if(k != -1) break; } ans[1] = j; getAns(n-1, c, j, k, ans + 1); for(i = n; i>=1; i–){ for(j=i+1; j<=n; j++) if(ans[j] >= ans[i]) ans[j]++; } for(j=1; j<=n; j++){ printf(“%d”, ans[j]); printf(j == n?\n:” “); } }

    int main() { Init(); scanf(“%d”, &t); for(int i=1; i<=t; i++){ scanf(“%d%lld”, &n, &c); print(n, c); } return 0; }

阅读全文