点名游戏-被小菜点名了
发表评论5次阅读2007.08.31 20:02 作者:Felicia 编辑
点名游戏的规则
- 被点到名字的要在自己的空间里写下自己的答案,然后去掉一个你最不喜欢的问题再加上一个你的问题,仍然组成19个问题,传给其他8个人,列出其他8个需要回答问题的人的名字,还要到这8个人的博客里留言通知对方–你被点名了,被点名者不得拒绝回答问题,完成游戏的人将会永远得到大家的祝福。
- 这8个人要在自己的博客里注明是从哪里接到的,并且再传给其他8个人,让游戏继续下去,不得回传。被点到名字的人将会得到大家的祝福,并且所有美好的愿望都会在不久的将来实现
下面是题目
1.你认为分手后的男女朋友还能做普通朋友吗?
回答:有的能,有的不能。不过我看过很多分手的情侣,他们多半不能够继续做朋友了。因为伤害太深,甚至见不得任何与以前伴侣有关的东西……
2.爱他(她)就一定要得到他(她)吗?
回答:不一定要得到。有时候就算想要,也有很多客观原因阻碍。没有缘分,再怎样爱都没有用。
3.半夜睡不着觉怎么办
回答:打死骚扰我的那只蚊子。
4.你最希望从朋友(不包括爱人)那里得到的是什么?
回答:嗯嗯,喜欢我就行。
5.最近最郁闷的事?
回答:最近不郁闷,心情不错。
6.你認爲什麽事情最浪漫?
回答:在屋顶上晒一个晚上的月亮。
7.你最喜欢自己哪一点?
回答:我是男生,谢谢。
8.如果可以,你希望现在谁可以立刻死掉?
回答:上帝。
9.最近最快乐的事情是什么?
回答:做了一些好题,把代码和解题报告贴在blog上了。每天都这么做很开心。
10.你知道爷爷奶奶的生日么?
回答:知道爷爷的,不知道奶奶的。奶奶很早就去世了。
11.遇到喜欢的人,你是勇敢表白还是默默关注?
回答:先看看她是否喜欢我,如果真的喜欢,那我就会表白。不过这是多年以前的事了。
12.说出点你名的人的3个优点(不可删除题)
回答:皮肤很好,讲义气,做事不含糊。
13 最怀念18年里的哪些人?
回答:A.高中的时候和我一起奋斗的OIer们。B.高一的时候和我一起进校的年轻老师们。
14.最想珍惜的人/事是什么 ?
回答:珍惜Ader,珍惜爱情。
15.你对你的近况满意吗?有什么需要改变?
回答:近况还不错。就是希望身体再好一点。
16.如果你的BF/GF和她/他的前任联系频繁,你有什么感受?
回答:不爽。这种感觉貌似被人称为吃醋。
17.最近有什么令你感动的事?
回答:妹妹关心我。
18.当最好的朋友误解你的时候,你会怎么做?
回答:误解意味着交流不够。我会跟他好好交流一下。
19.你相信并支持友情进化成爱情么?
回答:我相信。不过如果我支持的话,Ader会打我的。
去掉第 15 个问题。不大喜欢这个问题。
我的问题:你认为这19个问题再传多少次,会被全部改掉?
点名:mmd,cz,yama,lzx,dzs,zercal,Ader,vanish。
[动态规划] pku1947 树型DP
发表评论51次阅读2007.08.31 18:27 作者:Felicia 编辑
推荐此题。基础树型DP。
f[x][i](1 <= i <= p)表示以x为根的子树,变成剩下i个点的子树,且剩余子树包含根结点,需要去掉的最少边数。
那么父结点的f值可以由它所有的儿子的f值做背包得到。
最后的答案是min(min(f[i][p]) + 1 (2 <= i <= n), f[1][p])
下面是我的代码
Author: WHU_GCC
Created Time: 2007-8-31 12:40:35
File Name: pku1947.cpp
Description:
**********************************************************************/
#include <iostream>
#include <vector>
using namespace std;
#define out(x) (cout << #x << ": " << x << endl)
const int maxint = 0x7FFFFFFF;
typedef long long int64;
const int64 maxint64 = 0x7FFFFFFFFFFFFFFFLL;
template <class T> void show(T a, int n) {for (int i = 0; i < n; ++i) cout << a[i] << ' '; cout << endl; }
template <class T> void show(T a, int r, int l) {for (int i = 0; i < r; ++i) show(a[i], l); cout << endl; }
const int maxn = 160;
const int inf = 10000;
int n, p;
vector <int> v[maxn];
int f[maxn][maxn];
void dfs(int now)
{
for (int i = 0; i < v[now].size(); i++)
dfs(v[now][i]);
f[now][1] = v[now].size();
for (int i = 0; i < v[now].size(); i++)
for (int k = p - 1; k >= 0; k--) if (f[now][k] < inf)
{
for (int j = 1; j < p; j++) if (f[v[now][i]][j] < inf)
f[now][k + j] <?= f[now][k] + f[v[now][i]][j] - 1;
}
}
int dp()
{
for (int i = 1; i <= n; i++)
for (int j = 0; j <= n; j++)
f[i][j] = inf;
dfs(1);
int ret = inf;
for (int i = 2; i <= n; i++)
ret <?= f[i][p] + 1;
ret <?= f[1][p];
return ret;
}
int main()
{
while (scanf("%d%d", &n, &p) != EOF)
{
for (int i = 1; i <= n; i++) v[i].clear();
for (int i = 0; i < n - 1; i++)
{
int t1, t2;
scanf("%d%d", &t1, &t2);
v[t1].push_back(t2);
}
printf("%d\n", dp());
}
return 0;
}
[动态规划] pku1848 树型DP
发表评论30次阅读2007.08.30 21:47 作者:Felicia 编辑
强烈推荐此题。此题应用树型DP解答。
首先明确一点,题中的环至少需要3个顶点。因此,对于树中的每个顶点,有3种状态。
f[x][0]表示以x为根的树,变成每个顶点恰好在一个环中的图,需要连的最少边数。
f[x][1]表示以x为根的树,除了根x以外,其余顶点变成每个顶点恰好在一个环中的图,需要连的最少边数。
f[x][2]表示以x为根的树,除了根x以及和根相连的一条链(算上根一共至少2个顶点)以外,其余顶点变成每个顶点恰好在一个环中的图,需要连的最少边数。
有四种状态转移(假设正在考虑的顶点是R,有k个儿子):
A.根R的所有子树自己解决(取状态0),转移到R的状态1。即R所有的儿子都变成每个顶点恰好在一个环中的图,R自己不变。
B.根R的k-1个棵树自己解决,剩下一棵子树取状态1和状态2的最小值,转移到R的状态2。剩下的那棵子树和根R就构成了长度至少为2的一条链。
C.根R的k-2棵子树自己解决,剩下两棵子树取状态1和状态2的最小值,在这两棵子树之间连一条边,转移到R的状态0。
D.根R的k-1棵子树自己解决,剩下一棵子树取状态2(子树里还剩下长度至少为2的一条链),在这棵子树和根之间连一条边,构成一个环,转移到R的状态0。
这样就完成了树型DP。
[动态规划][图论] pku1112 背包
1个评论30次阅读2007.08.29 17:15 作者:Felicia 编辑
强烈推荐此题。图论和DP结合。
首先,我们分析一下分组的要求:
- 把所有的人分成2组,每组至少有1人;
- 每组之间的人两两认识。
非常明显,如果存在两个人A和B,A不认识B,或B不认识A,那么A和B一定不能分在同一组。因此,我们以人为结点重新构造一个图G。假如A和B不能分在同一组,那么就在G中增加一条无向边(A,B)。这样,我们就得到了一个较为”单纯”的模型。下面我们对这个模型进行简单分析。
我们先研究G的一个连通分量K1。对于这个连通分量,可以先求出K1的生成树T1。对于K1中的任意结点a,假如a在T1中的深度为奇数,我们就把a加入点集S1;否则我们把a加入点集S2(S1,S2最初为空集)。显然最后S1,S2的交集为空。
不难证明,如果存在不同结点p和q,p和q同属于S1或S2,而且G中存在边(p,q),那么要做到满足题目要求的分组是不可能的,应输出No solution。否则,我们就得到了连通分量K1的唯一分组方案:分为S1,S2两组。
对于G中的每个连通分量Ki,我们可以求出相应的S1i,S2i。最后,我们的目的是把全部人分为2组。也就是说,对于i=1,2,3,…,m,我们必须决定把S1i中的人分到第1组,S2i中的人分到第2组,还是做刚好相反的处理。由于题目要求最后两组的总人数差最小,我们可以用动态规划的办法来确定究竟选取上面的哪种决策。
不妨假设G中共有m个连通分量,记|S1i|=xi,|S2i|=yi(i=1,2,3,…,m)。若xi < yi,我们就交换xi和yi(这样不影响结果的正确性)。记wi = xi – yi。那么只要对所有的wi做”半个背包”即可。也就是说,凑出尽量接近sum(wi)的数。接下去就非常简单了。
下面是我的代码
Author: WHU_GCC
Created Time: 2008-9-29 12:07:38
File Name: pku1112.cpp
Description:
**********************************************************************/
#include <iostream>
#include <vector>
using namespace std;
#define out(x) (cout << #x << ": " << x << endl)
const int maxint = 0x7FFFFFFF;
typedef long long int64;
const int64 maxint64 = 0x7FFFFFFFFFFFFFFFLL;
template <class T> void show(T a, int n) {for (int i = 0; i < n; ++i) cout << a[i] << ' '; cout << endl; }
template <class T> void show(T a, int r, int l) {for (int i = 0; i < r; ++i) show(a[i], l); cout << endl; }
const int maxn = 110;
int n;
int g[maxn][maxn];
int cnt_id;
int id[maxn];
int w[maxn];
void dfs(int now, int new_id)
{
id[now] = new_id;
for (int i = 1; i <= n; i++) if (id[i] == 0 && g[now][i])
dfs(i, new_id);
}
void make_id()
{
cnt_id = 0;
memset(id, 0, sizeof(id));
for (int i = 1; i <= n; i++) if (id[i] == 0)
dfs(i, ++cnt_id);
}
int set_mask[maxn];
void divide(int cid, int now, int set_id, int *set_mask)
{
*(set_mask + now) = set_id;
for (int i = 1; i <= n; i++) if (*(set_mask + i) == 0 && id[i] == cid && g[now][i])
divide(cid, i, 3 - set_id, set_mask);
}
int ok()
{
memset(set_mask, 0, sizeof(set_mask));
for (int i = 1; i <= cnt_id; i++)
{
for (int j = 1; j <= n; j++)
if (id[j] == i)
{
divide(i, j, 1, set_mask);
break;
}
int cntx = 0;
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 1)
cntx++;
int cnty = 0;
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 2)
cnty++;
if (cntx < cnty)
{
for (int j = 1; j <= n; j++) if (id[j] == i)
set_mask[j] = 3 - set_mask[j];
}
w[i] = abs(cntx - cnty);
int flag = 1;
for (int j = 1; j <= n && flag; j++) if (id[j] == i && set_mask[j] == 1)
for (int k = 1; k <= n && flag; k++) if (id[k] == i && set_mask[k] == 1 && j != k)
if (g[j][k]) flag = 0;
for (int j = 1; j <= n && flag; j++) if (id[j] == i && set_mask[j] == 2)
for (int k = 1; k <= n && flag; k++) if (id[k] == i && set_mask[k] == 2 && j != k)
if (g[j][k]) flag = 0;
if (flag == 0) return 0;
}
return 1;
}
typedef struct ptr_t
{
int ptr, value;
};
ptr_t pre[maxn];
int mask[maxn];
void print(int now)
{
if (pre[now].value == 0)
return;
print(pre[now].ptr);
mask[pre[now].value] = 1;
}
void dp()
{
int f[maxn];
memset(f, 0, sizeof(f));
memset(pre, 0, sizeof(pre));
f[0] = 1;
int sum = 0;
for (int i = 1; i <= cnt_id; i++) sum += w[i];
for (int i = 0; i <= cnt_id; i++)
for (int j = sum / 2; j >= 0; j--) if (f[j] && !f[j + w[i]])
{
f[j + w[i]] = 1;
pre[j + w[i]].ptr = j;
pre[j + w[i]].value = i;
}
int ans_i;
for (int i = sum / 2; i >= 0; i--) if (f[i])
{
ans_i = i;
break;
}
memset(mask, 0, sizeof(mask));
print(ans_i);
int cnt1 = 0;
for (int i = 1; i <= cnt_id; i++)
{
if (mask[i])
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 1)
cnt1++;
}
else
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 2)
cnt1++;
}
}
printf("%d", cnt1);
for (int i = 1; i <= cnt_id; i++)
{
if (mask[i])
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 1)
printf(" %d", j);
}
else
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 2)
printf(" %d", j);
}
}
printf("\n");
int cnt2 = 0;
for (int i = 1; i <= cnt_id; i++)
{
if (mask[i])
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 2)
cnt2++;
}
else
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 1)
cnt2++;
}
}
printf("%d", cnt2);
for (int i = 1; i <= cnt_id; i++)
{
if (mask[i])
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 2)
printf(" %d", j);
}
else
{
for (int j = 1; j <= n; j++) if (id[j] == i && set_mask[j] == 1)
printf(" %d", j);
}
}
printf("\n");
}
int main()
{
int tmp[maxn][maxn];
while (scanf("%d", &n) != EOF)
{
memset(tmp, 0, sizeof(tmp));
for (int i = 1; i <= n; i++)
{
int t;
while (scanf("%d", &t), t != 0)
tmp[i][t] = 1;
}
memset(g, 0, sizeof(g));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j && (tmp[i][j] == 0 || tmp[j][i] == 0))
g[i][j] = g[j][i] = 1;
make_id();
int t = ok();
if (!t)
printf("No solution\n");
else
dp();
}
return 0;
}
