A. Prison Break
nm矩形方格代表监狱房间,最少在多少个墙壁上打洞,使得无论位于监狱的哪个房间都能逃走。
思路:根据例子构造解,并证明此解最优
易构造S型通路,res=mn;
观点(1)、递归
(2)保证一条欧拉路(考虑入度和出度)
直接输出n*m即可,代码略
(3)染色法(朋友提出的,本人未试)
输出m*n,代码略
B. Restore Modulo
给定数组a,判断能否按以下方法构造:
存在n,m,c,s; n,m>0;0<=c<m;s>=0。
(1) a1 = s (mod m)
(2) a i = a i-1 +c (mod m) i=1…n;
如果存在,并找出最大的m,以及任意符合要求的c
思路:
注意到0<=c<m,于是 a i = a i-1 +c (mod m) 等价为——
根据a i - a i-1的正负性(1)a i - a i-1 = c (2) a i - a i-1 = c -m
故构造差分数组dd,并将其划分——负数一类dn,非负一类dp
分情况讨论,探索到什么时候不存在,什么m无穷大
不存在<=>dn元素不全相等,dp内元素不全相等
|| 算出的m不符合题中范围(易忽略!)
m无穷大<=>dn和dp有一个为空
剩余情形根据(1)a i - a i-1 = c (2) a i - a i-1 = c -m即算出m,c
代码如下:
#include<iostream>
#include<stdio.h>
#include<vector>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<unordered_set>
#include<set>
#include<map>
#include<sstream>
using namespace std;
#define int long long
const int INT = 0x3f3f3f3f;
unsigned main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int>nums;
vector<int>dp;
vector<int>dn;
int ma = 0;
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
nums.push_back(x);
ma = (x > ma) ? x : ma;
}
for (int i = 0; i < n - 1; ++i) {
int y = nums[i+1] - nums[i];
if (y >= 0)
dp.push_back(y);
else
dn.push_back(y);
}
int len1 = dp.size(), len2 = dn.size();
int flag = 1, p = -1, q = 1;
if (len1) {
int temp = dp[0];
for (auto i : dp) {
if (i != temp) {
flag = 0;
break;
}
}
if (flag)
p = temp;
}
if (len2) {
int temp = dn[0];
for (auto j : dn) {
if (j != temp) {
flag = 0;
break;
}
}
if (flag)
q = temp;
}
int c = p, m = p - q;
if (p>=0 && q<0 && m <= ma) {
flag = 0;
}
if (flag == 0) {
cout << -1 << "\n";
continue;
}
if (len1 == 0 || len2 == 0) {
cout << 0 << "\n";
continue;
}
cout << m << " " << c << "\n";
}
}
C. Basic Diplomacy
n个朋友,m天,每天找一个朋友玩,每个朋友玩的天数不能超过(m/2)上取整给出m天中每天哪些朋友有空。判断是否满足要求,是则给出方案。
分析:
注意到对任何一种选择方法(先不考虑题目限制),最多一人(A)天数cnt(A)超过(m+1)/2。对这种方法,遍历每一天,如果这一天选了A,看看这一天可选的朋友除了A有没有其他人——如果有,则替换,–cnt(A)。m天遍历完后最后看是否符合要求。
代码如下:
#include<iostream>
#include<stdio.h>
#include<vector>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<unordered_set>
#include<set>
#include<map>
#include<sstream>
using namespace std;
#define int long long
const int INT = 0x3f3f3f3f;
unsigned main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
vector<int>ans;
vector<vector<int>>arr(m);
vector<int>cnt(n+1,0);
for (int i = 0; i < m; ++i) {
int k,x;
cin >> k;
for (int j = 0; j < k; ++j) {
cin >> x;
arr[i].push_back(x);
}
cnt[x]++;
ans.push_back(x);
}
for (int i = 0; i < m; ++i) {
if (cnt[ans[i]] > (m + 1) / 2) {
if (arr[i].size() >= 2) {
--cnt[ans[i]];
ans[i] = arr[i][0];
}
}
}
int flag = 1;
for (int i = 0; i < m; ++i) {
if (cnt[ans[i]] > (m + 1) / 2) {
flag = 0;
break;
}
}
if (flag) {
cout << "YES\n";
for (int i = 0; i < m; ++i) {
cout << ans[i] << " ";
}
cout << endl;
}
else {
cout << "NO\n";
}
}
}