比賽鏈接:https://zhixincode.com/contest/17
A 奪寶奇兵
題解:因爲是先從1->n再從n->1,所以我們可以考慮當成一遍走,即每次的選擇無非。然後取再加上即可。
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 100100;
struct node{
int x,y;
}a[N],b[N];
int dis(node u,node v)
{
return abs(u.x - v.x) + abs(u.y - v.y);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n,m;
cin >> n >> m;
long long ans = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d %d %d %d",&a[i].x,&a[i].y,&b[i].x,&b[i].y);
if(i == 1) continue;
ans += min(dis(a[i - 1], a[i]) + dis(b[i - 1], b[i]), dis(a[i - 1], b[i]) + dis(b[i - 1], a[i]));
}
cout << ans + dis(a[n],b[n]) << endl;
return 0;
}
C 最小邊覆蓋
題解:易發現對於每一條邊,兩點的度都大於1,那麼這條邊就是多餘的。
#include<bits/stdc++.h>
using namespace std;
const int N = 3E5+10;
int cnt[N], u[N],v[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n,m;
cin >> n >> m;
for(int i = 0; i < m; ++i) {
scanf("%d %d",&u[i],&v[i]);
cnt[u[i]]++;
cnt[v[i]]++;
}
for(int i = 0; i < m; ++i) {
if(cnt[u[i]] > 1 && cnt[v[i]] > 1) {
return puts("No"),0;
}
}
puts("Yes");
return 0;
}
F 小小馬
題解:對於以上的矩陣,我們可以知道是可以到達任意一個點的。然後我們判斷起點和終點的顏色即可,因爲每次移動點的顏色是黑白交替的。然後小矩陣窩採用的是爆搜,雖然特判一下也可以。
#include<bits/stdc++.h>
using namespace std;
int dir[8][2] = {-2,-1, -2,1, -1,-2, -1,2, 1,-2, 1,2, 2,-1, 2,1};
bool vis[11][11];
int n,m,sx,sy,ex,ey,rec;
bool isWhite(int x,int y)
{
return (x & 1) == (y & 1);
}
void dfs(int x,int y,int white,int black)
{
if(x == ex && y == ey) {
if(white == black) {
rec = 1;
return;
}
}
for(int i = 0; i < 8; ++i) {
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if(tx < 1 || tx > n || ty > m || ty < 1 || vis[tx][ty])
continue;
vis[tx][ty] = 1;
if(isWhite(tx,ty)) white++;
else black++;
dfs(tx,ty,white,black);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
#endif
cin >> n >> m >> sx >> sy >> ex >> ey;
if (n >= 3 && m >= 3) {
if ((sx == 2 && sy == 2) || (ex == 2 && sy == 2)) {
puts("No");
return 0;
}
if (isWhite(sx, sy) == isWhite(ex, ey))
puts("No");
else
puts("Yes");
} else {
if(n == 2) {
int k1 = abs(sy - ey);
if(abs(sx - ex) == 1 && k1 % 2 == 0 && k1 % 4 != 0) {
puts("Yes");
}else{
puts("No");
}
return 0;
}else if(m == 2){
int k1 = abs(sx - ex);
if(abs(sy - ey) == 1 && k1 % 2 == 0 && k1 % 4 != 0) {
puts("Yes");
}else{
puts("No");
}
return 0;
}
int white = 0, black = 0;
if (isWhite(sx, sy)) white++;
else black++;
dfs(sx, sy, white, black);
puts(rec ? "Yes" : "No");
}
return 0;
}
置置置換
題解:考慮第個數的排列末尾位置爲的方案數。
如果爲奇數
如果爲偶數,我們可以考慮將前面比大的數都加一,這樣就有
這樣做是,但是我們發現每次都是從轉移過來,所以可以前綴和優化一下。
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
long long dp[1010][1010];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n;
cin >> n;
dp[1][1] = 1;
for(int i = 2; i <= n; ++i) {
for(int j = 1; j <= i; ++j) {
if(i & 1) {
dp[i][j] = (dp[i][j - 1] + dp[i - 1][j - 1]) % mod;
}else{
dp[i][j] = (dp[i][j - 1] + dp[i - 1][i - 1] - dp[i - 1][j - 1] + mod) % mod;
}
}
}
cout << dp[n][n] << endl;
return 0;
}
I 咆咆咆哮
題解:因爲至少總體攻擊力增加,而是對在場所有單體加成,因次最優方案必定是把所有上完,再釋放。所以我們可以考慮貪心枚舉的個數。但是怎麼貪心呢?假設我們當前選了個,那麼我們將其中第個卡片換成,所獲得的收益是,因此我們可以以此來排序從而優先選擇收益大的。
#include<bits/stdc++.h>
using namespace std;
struct node{
int a,b;
long long c;
bool operator < (const node & u) const {
return c > u.c;
}
}f[1010];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n;
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> f[i].a >> f[i].b;
}
long long ans = 0, sum = 0;
for(int i = 1; i <= n; ++i) {
sum = 0;
for(int j = 1; j <= n; ++j) {
f[j].c = f[j].a - f[j].b * i;
}
sort(f + 1, f + n + 1);
for(int j = 1; j <= i; ++j) {
sum += f[j].a;
}
for(int j = i + 1; j <= n; ++j) {
sum += f[j].b * i;
}
ans = max(ans, sum);
}
cout << ans << endl;
return 0;
}