FZU 10月月赛

来源:互联网 发布:java 格式化xml字符串 编辑:程序博客网 时间:2024/04/30 13:18
 Problem E 犯罪嫌疑人

Accept: 82    Submit: 387
Time Limit: 1000 mSec    Memory Limit : 65536 KB

 Problem Description

福尔摩斯是个大侦探,他总是在解决疑难案件。这一次的案件也不例外,案件是这样的:有编号为1到N的N位嫌疑犯,他们其中有一个犯了罪,然后每个嫌疑犯都被询问,“哪一个人犯了罪?”犯罪嫌疑人的答案只能“编号ai的嫌疑犯犯了罪”或者“编号ai的嫌疑犯没有犯罪”。当然嫌疑犯也可以说他自己(ai = i).

福尔摩斯凭着他敏锐的侦探直觉,确定地对华生说,只有M个人说了真话,其余人都是说谎。然后就没有然后了,但华生却想知道哪些人说谎哪些人又是讲真话。这个时候同样聪明的你,被誉为红旗下的名侦探是否愿意秀一下自己的侦探天赋,帮助可怜的华生嘛?

 Input

第一行一个整数T(1 <= T <= 10),表示测试数据的组数。

每组数据第一行包含N(1 <= N <=10^5)和M(0 <= M <= N)两个整数,含义见题面。接下来N行,第i行是一个整数+ai或者-ai(1<= ai <= N),如果是+ai,代表第i个人说编号ai犯了罪,如果是-ai,则表示编号ai没有犯罪。

输入数据保证至少存在一个人,使得如果是他犯了罪,则恰好有 M 个人说了真话。

 Output

输出为N行,第i行是第i个嫌疑犯的输出。如果第i个嫌疑犯说了是真话,输出“Truth”;如果说谎,则输出“Lie”,如果不确定,则输出“Not defined”。

 Sample Input

2
3 2
-1-2-3
4 1
+2-3+4-1

 Sample Output

Not defined
Not defined
Not defined

Lie
Not defined
Lie
Not defined

思路:模拟+推理
题目已经说明如果某个人犯罪,那么恰好有m个人说了真话。
那么我们就预先出来每个人都犯罪的情况,判断当哪个人犯罪了恰好有m个人说了真话,那么就可以判断这个人就是嫌疑犯
如果最后嫌疑犯只有一个,那么这个人就是犯罪人,如果最后嫌疑犯不止一个,那么这些嫌疑犯都有可能是真正的罪犯。
总结:
对于第i个人犯罪:说真话的数目=说“i是罪犯”的数目+说“除i以外的人没犯罪”的数目(相当于没犯罪的句子数-说i没犯罪的句子数)
如果最后嫌疑犯只有一个【比如是i】:那么说“i是罪犯”和说“(除i以外的)人不是犯罪”的人说的是真话。其他都是假话。
如果最后嫌疑犯不止一个【嫌疑犯集合:i表示在集合里,j表示不在集合里】:那么
说“i是罪犯”和“i不是罪犯”的人可能是真可能是假。
说“j不是犯罪”是真话【因为j不在嫌疑集合里】
说“j是犯罪”是假话【因为j不在嫌疑犯集合里】

#include<iostream>#include<cstring>using namespace std;const int MAXN = 100005;int t, n, m, yes[MAXN], no[MAXN], num[MAXN];//yes[i]:说i是罪犯的句子数,no[i]:说i不是罪犯的句子数,num[i]:i所说的话int main(){cin >> t;while (t--){int index[MAXN], no_sum = 0, ans = 0;//嫌疑犯下标,总不是嫌疑犯的句子数,嫌疑犯个数memset(yes, 0, sizeof(yes));memset(index, 0, sizeof(index));memset(no, 0, sizeof(no));cin >> n >> m;for (int i = 1; i <= n; i++){cin >> num[i];if (num[i] >0){yes[num[i]]++;}else{no[(num[i] * -1)]++;no_sum++;}}for (int i = 1; i <= n; i++)//找嫌疑犯,假设i犯罪了{int sum = 0;sum += yes[i];//说i是罪犯sum += no_sum - no[i];//除i以为的人不是罪犯if (sum == m)//恰好有m句真话{index[ans++] = i;//加入嫌疑犯序列}}if (ans == 1)//只要一个嫌疑犯{for (int i = 1; i <= n; i++){if (num[i]>0){if (num[i] == index[0]){cout << "Truth" << endl;}else{cout << "Lie" << endl;}}else{if ((num[i] * -1) == index[0]){cout << "Lie" << endl;}else{cout << "Truth" << endl;}}}}else//存在多个嫌疑犯{for (int i = 1; i <= n; i++){int j;for (j = 0; j < ans; j++){if ((num[i] == index[j]) || (num[i] * -1) == index[j]){cout << "Not defined" << endl;break;}}if (j == ans){if (num[i] >0){cout << "Lie" << endl;}else{cout << "Truth" << endl;}}}}}//system("pause");return 0;}


 Problem 2203 单纵大法好

Accept: 53    Submit: 128
Time Limit: 5000 mSec    Memory Limit : 65536 KB

 Problem Description

人在做,天在看,单纵不怂保平安

众娘皆为轮回来,敢教POI进夜战。

勿怪战列低智商,航母不是一个样?

假摔不虚有损管,大破进击是真相!

老S最近喜欢上某个搜集战舰的游戏,这个游戏中很重要的一个内容是能编排自己的战舰,通过出击完成任务来获取资源或新的战舰。大家都说老S是一个“直男”,所以他喜欢把战舰排成一条直线。目前老S正准备完成某个新的任务--“困难级丹麦海峡”,可以将地图视为1*N的一列方格(下标为1,2,...,N),老S有K列战舰,每列战舰长度为A。老S可以将自己的战舰布局在地图中的任意位置,但是两列战舰之间至少要有一个空格子,并且显然战舰是不能重叠放置的。老S通过内部人员率先知道了敌军的炮弹将会打向那些位置,老S希望使自己的舰队尽量晚的被第一次击中。请输出老S的舰队最晚将被敌方炮弹第一次击中?如果老S的舰队可以不被敌方炮弹击中则输出-1。

 Input

包含多组数据

每组数据第一行有3个整数分别为N,K,A 分别表示地图长度,老S拥有的战舰数,每艘战舰的长度。(1<=N,K,A<=200000)

第二行有1个整数M,表示敌方炮弹数。 (1<=M<=N)

第三行有M个整数,Xi表示第i个敌方炮弹将击中位置Xi (1<=Xi<=N)击中位置Xi (1<=Xi<=N)

 Output

仅有一个整数ANS,表示老S最晚将被哪个炮弹第一次击中

 Sample Input

5 1 321 55 1 313

 Sample Output

-11


思路:因为炮弹的轰炸时间顺序是递增的,并且时间越往后,能放置船只的位置就越少。
所以可以二分时间找满足条件的时间,如果对于某个时间t,如果t-1时间后能放置所以船只免受轰击
而t时间后不能放置所以船只免受轰击即找到了满足条件的t。
注意:每个船只直接要有至少一个单位间隔。
#include<iostream>#include<cstring>#include<stdio.h>using namespace std;const int MAXN = 200005;int n, m, k, a;int pos[MAXN];bool suff(int t){int num = 0, vis[MAXN];memset(vis, 0, sizeof(vis));for (int i = 1; i <= t; i++)//对于t秒,哪些位置不能能放船{vis[pos[i]] = 1;}int yes_p = 0;for (int i = 1; i <= n; i++)//判断剩余的位置能否放所有船只{if (!vis[i]){yes_p++;}else{num += (yes_p + 1) / (a + 1);yes_p = 0;}}num += (yes_p + 1) / (a + 1);if (num >= k){return true;}else{return false;}}int main(){while (scanf("%d %d %d", &n, &k, &a) != EOF){scanf("%d", &m);//炮弹的数量for (int i = 1; i <= m; i++){scanf("%d", &pos[i]);//第i秒炮弹轰击的位置}bool s = false;int l = 1, r = m, mid;while (r >= l){bool s1, s2;mid = (l + r) / 2;s1 = suff(mid);s2 = suff(mid - 1);if (s1 == false && s2 == true){s = true;break;}if (s1){l = mid + 1;}else{r = mid - 1;}}if (s){printf("%d\n", mid);}else{printf("-1\n");}}//system("pause");return 0;}

C【环DP】和G是【三维DP】
DP太弱了写不来。T T
0 0
原创粉丝点击