链接:https://www.nowcoder.com/acm/contest/134/A
来源:牛客网
对于每个询问输出一行表示答案,如果删除木棍后无法组成三角形则输出 -1 。
思路:
按照三角形最长边小于其余两边之和来从长到短选择最长边。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
typedef struct Node{
int v, id;
bool operator < (const Node &rhs) const{
return v < rhs.v;
}
}Node;
vector p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> k;
p.resize(n);
for(int i = 0; i < n; i++){
cin >> p[i].v;
p[i].id = i;
}
sort(p.begin(), p.end());
while(k--){
int ban;
cin >> ban;
ban--;
ll res = -1;
for(int i = n - 1; i >= 2; i--){
if(p[i].id == ban)
continue;
int sum = 0;
for(int j = i - 1, cnt = 0; j >= 0 && cnt < 2; j--)
if(p[j].id == ban)
continue;
else{
cnt++;
sum += p[j].v;
}
if(sum > p[i].v){
res = (ll)sum + (ll)p[i].v;
break;
}
}
cout << res << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/B
来源:牛客网
第一行一个数字n。(1 ≤ n ≤ 1000) 第二行n个数字di。(0 ≤ di ≤ 9)
输出一个数字表示答案。
思路:
从小到大猜。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
bool zero = false;
for(int i = 0; i < n; i++)
if(p[i] == zero){
zero = true;
break;
}
if(!zero)
cout << 0 << endl;
else{
for(int i = 0; ; i++){
bool found = false;
for(int j = n - 1; j >= 0; j--){
int clone = i, t = j;
while(t >= 0 && clone && clone % 10 == p[t]){
t--;
clone /= 10;
}
if(!clone){
found = true;
break;
}
}
if(!found){
cout << i << endl;
break;
}
}
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/C
来源:牛客网
第一行两个整数n,m。n表示方格的规格,m表示最初病菌所在的格子数。(1 ≤ n ≤ 1000, 0 < m < n)。
如果最终所有的方格都会被感染,输出 YES。 否则输出 NO。
思路:
可以直观发现,只有当m >= n时才会铺满整个培养皿。
因为只有有两个相邻的感染才能被感染,也就是说如果要让(i,j)感染,i行或者i + 1行必须要有感染的才有可能。
如果m < n,显然无法使得所有行都感染。
如果m == n,放对角线就可以了。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m;
if(m >= n)
cout << "YES" << endl;
else
cout << "NO" << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/D
来源:牛客网
第一行三个整数n, m, R(2 ≤ n ≤ 200, 1 ≤ m ≤ 5000, 2 ≤ R ≤ min(n, 15))。 第二行R个整数表示需要去玩耍的郊区编号。 以下m行每行Ai, Bi, Ci(1 ≤ Ai, Bi ≤ n, Ai ≠ Bi, Ci ≤ 10000) 保证不存在重边。
输出一行表示最小的花费
思路:
floyd预处理,然后用dp记录结果枚举。
dp[i][j],i代表此时的状态,j代表最后一次选的点。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
vii path, dp;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m >> k;
p.resize(k);
for(int i = 0; i < k; i++){
cin >> p[i];
p[i]--;
}
path.resize(n, vi(n, INF));
for(int i = 0; i < m; i++){
int u, v, c;
cin >> u >> v >> c;
u--;
v--;
path[u][v] = c;
path[v][u] = c;
}
for(int i = 0; i < n; i++)
path[i][i] = 0;
for(int t = 0; t < n; t++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
path[i][j] = min(path[i][j], path[i][t] + path[t][j]);
dp.resize(1 << k, vi(k, INF));
for(int i = 0; i < k; i++)
dp[1 << i][i] = 0;
for(int i = 0; i < (1 << k); i++){
for(int j = 0; j < k; j++){
if(!(i & (1 << j)))
continue;
for(int t = 0; t < k; t++){
if((1 << t) & i)
continue;
dp[i | (1 << t)][t] = min(dp[i | (1 << t)][t], dp[i][j] + path[p[j]][p[t]]);
}
}
}
int res = INF;
for(int i = 0; i < k; i++)
res = min(res, dp[(1 << k) - 1][i]);
cout << res << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/E
来源:牛客网
输入只有一行,一个浮点数。保证数据合法,不存在整数位的前导零以及小数位的后导零。
输出只有一行,一个浮点数。
思路:
用来启发人们发现计算机的浮点数是有误差的。
把输入当字符串处理即可。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
string str;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> str;
cout << str << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/F
来源:牛客网
一串长度为 n 的字符串 A 和一串长度为 m 的字符串 B。并且这两串字符串只会含有 0 或 1 。
铁子可以对字符串 A 执行两种操作,两种操作可以执行任意次。
操作1(无情替换):铁子可以用 11 替换掉 0 ,也可以用 00 替换掉 1 .
操作2(极限删除):铁子可以删除掉 111 ,也可以删除 000 .
现在问,字符串 A 可以变成字符串 B 吗?
第一行有一个整数T,表示有T(1<=T<=1000)组测试数据。 接下来的每组数据,第一行有两个整数n,m(1<=n,m<=100),表示字符串A和字符串B的长度。 接下来有两行字符串,分别表示字符串A和字符串B。
对于每组测试数据,如果字符串A可以变为字符串B,则输出一行”YES”,否则输出一行”NO”.输出不包括引号。
思路:
可以发现顺序是无关的,也就是说001一定可以从100或者010转换而来。
又可以发现,1可以自增成1111(4个1)或者1111111(7个1),也就是说可以自增3n的长度,当然n属于R。
那么现在需要做的就是把A和B都转化成0或者1的串,然后判断他们长度之间的关系。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
string str, ptr;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
int times;
cin >> times;
while(times--){
cin >> n >> m;
cin >> str >> ptr;
int res = 0;
for(int i = 0; i < n; i++)
res += 1 + str[i] - '0';
for(int i = 0; i < m; i++)
res -= 1 + ptr[i] - '0';
if(res % 3)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/G
来源:牛客网
每行两个数字x,y代表落子坐标(1 ≤ x,y ≤ 8) 以EOF结束下子,保证下子的正确性以及合法性,下完最后一颗子代表棋局结束。 ps:emmmm... 貌似有点长,不要慌,问题不大(雾
输出一行,黑方与白方的棋子数量之比a:b
思路:
有研究黑白棋的朋友吗?
从这题中我感受到了黑白棋的魅力,首先如果棋盘是n*m,那么最多放n*m - 4个棋,而且只要知道放的棋的位置,甚至不用知道先后顺序和颜色,就一定可以复原成唯一的棋盘。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
const int dr[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dc[] = {-1, 0, 1, -1, 1, -1, 0, 1};
int n, m, k;
vi x, y, p;
vii mat, inq;
void recur(int depth, int id){
int u, v;
if(depth > (int)x.size())
return;
bool found = false;
for(int i = 0; i < (int)x.size(); i++){
u = x[i];
v = y[i];
if(mat[u][v] >= 0)
continue;
for(int dir = 0; dir < 8; dir++){
int cnt = 0;
int uu = u + dr[dir];
int vv = v + dc[dir];
if(!(uu > 0 && vv > 0 && uu <= 8 && vv <= 8))
continue;
if(mat[uu][vv] == id)
continue;
while(cnt < 3 && uu > 0 && vv > 0 && uu <= 8 && vv <= 8 && mat[uu][vv] >= 0){
cnt |= (1 << mat[uu][vv]);
if(cnt == 3)
break;
uu += dr[dir];
vv += dc[dir];
}
if(cnt == 3){
found = true;
while(u != uu || v != vv){
mat[u][v] = mat[uu][vv];
u += dr[dir];
v += dc[dir];
}
u = x[i];
v = y[i];
}
}
if(found)
return recur(depth + 1, id ^ 1);
}
return recur(depth, id ^ 1);
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
mat.resize(10, vi(10, -1));
inq.resize(100, vi(5));
mat[4][4] = mat[5][5] = 0;
mat[5][4] = mat[4][5] = 1;
int u, v;
while(cin >> u >> v){
x.push_back(u);
y.push_back(v);
}
recur(1, 1);
p.resize(2);
for(int i = 1; i <= 8; i++)
for(int j = 1; j <= 8; j++){
if(mat[i][j] < 0)
continue;
p[mat[i][j]]++;
}
cout << p[1] << ":" << p[0] << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/H
来源:牛客网
第一行三个数字n, m, x(2 ≤ n,m ≤ 106,1 ≤ x ≤ 109)。 第二行n个数字(1 ≤ ai ≤ 109)。
输出一个操作数,代表实现要求的最少操作数。
思路:
利用滑动窗口的想法,从左到右扫描,优先吃掉右边的。
不必害怕是否会退化成(nm), 可以证明,当此时扫到i时,i - m退出,如果此时val[i] > val[i - m]那才有可能要吃,而且只用吃一个。
实际复杂度为O(n)。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vll p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m >> k;
p.resize(n + 1);
for(int i = 1; i <= n; i++)
cin >> p[i];
ll cur = 0, res = 0;
for(int i = 1; i <= min(n, m - 1); i++)
cur += p[i];
for(int i = min(n, m); i <= n; i++){
cur += p[i];
for(int j = i; cur > k; j--){
ll cal = min(cur - k, p[j]);
res += cal;
p[j] -= cal;
cur -= cal;
}
cur -= p[i - m + 1];
}
cout << res << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/I
来源:牛客网
第一行一个数字n表示铁子班级的总人数。1≤n≤105 第二行一个字符串s表示最初的队形布置,si=0表示第i个人是女生,si=1表示第i个人是男生。
输出一行表示答案
思路:
思考这样一种情形,可以改变一个人的性格,问最长的连续女生是多少?
这个问题可以转换成上述情形,最后只用输出min(女生总人数,上述情形计算结果)即可;
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
string str;
vii dp;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
dp.resize(n, vi(2));
cin >> str;
cerr << str << endl;
int res = 0, cnt = 0;
cnt = dp[0][0] = !(str[0] - '0');
dp[0][1] = 1;
for(int i = 1; i < n; i++){
if(!(str[i] - '0')){
cnt++;
dp[i][0] = dp[i - 1][0] + 1;
dp[i][1] = dp[i - 1][1] + 1;
}
else{
dp[i][0] = 0;
dp[i][1] = dp[i - 1][0] + 1;
}
res = max(res, max(dp[i][0], dp[i][1]));
}
cout << min(res, cnt) << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
链接:https://www.nowcoder.com/acm/contest/134/J
来源:牛客网
第一行一个整数n表示序列的长度(1≤n≤105) 第二行n个整数ai表示序列的每个整数(1≤ai≤109)
输出一行表示答案
思路:
首先先要理解题意,发现可以除去一个元素,但要加入一个新元素,为了不使新元素有任何影响,让新元素比任何元素大即可。
这样就可以排除新元素的影响, 题意也就可以变成要除去多少个元素使得序列无重复元素。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector vi;
typedef vector vii;
typedef vector vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
sort(p.begin(), p.end());
cout << n - (unique(p.begin(), p.end()) - p.begin()) << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
未来可期。