T1
#include
using namespace std;
int main() {
int a, b, c;
cin >> a >> b >> c;
cout << a/5 + b/10*3+c/2 << endl;
return 0;
}
T2
我用的是字符串,其实用模运算更好
#include
#include
#include
#include
#include
using namespace std;
struct Bok {
string name;
int l;
};
Bok Book[5001];
int n, q;
int Bk[5001];
string Numb[5001];
int main() {
int len;
cin >> n >> q;
for(int i=1; i<=n; i++) {
cin >> Bk[i];
}
sort(Bk+1, Bk+n+1);
for(int i=1; i<=n; i++) {
stringstream turn;
turn << Bk[i];
turn >> Book[i].name;
Book[i].l = Book[i].name.size();
}
bool fod;
for(int i=1; i<=q; i++) {
fod = 0;
cin >> len;
cin >> Numb[i];
for(int j=1; j<=n; j++) {
bool Include = false;
int indx;
for(int k=0; k
T3
记忆化搜索算是一种简单的做法
#include
#include
using namespace std;
#define MAX 1e9
int m, n;
int Chess[1001][1001]; //棋盘,0表示无色
int dir[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
int f[1001][1001]; //记忆化:f[i][j]表示到(i, j) 的最小花费
void DFS(int a, int b, int sum, bool can_flog) { //坐标(a,b), 花费-sum, 能否使用魔法-can_flog
if(a < 1 || a > m || b < 1 || b > m) return;
if(sum >= f[a][b]) return; //根据记忆化 剪枝
f[a][b] = sum;
if(a == m && b == m) return;
for(int i=0; i<4; i++) {
int next_x = a + dir[i][0];
int next_y = b + dir[i][1];
if(next_x < 1 || next_x > m || next_y < 1 || next_y > m) continue;
if(Chess[next_x][next_y] == 0) {
if(!can_flog) continue;
Chess[next_x][next_y] = Chess[a][b]; //把下一个格子变为当前格子的颜色
DFS(next_x, next_y, sum + 2, false); //不能再用魔法了,can_flog = false
Chess[next_x][next_y] = 0; //记得回溯
} else {
if(Chess[next_x][next_y] != Chess[a][b]) DFS(next_x, next_y, sum + 1, true);
else if(Chess[next_x][next_y] == Chess[a][b]) DFS(next_x, next_y, sum, true);
}
}
}
int main() {
int x, y, color;
cin >> m >> n;
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
f[i][j] = MAX;
for(int i=1; i<=n; i++) {
cin >> x >> y >> color;
Chess[x][y] = color + 1;
}
DFS(1, 1, 0, true);
if(f[m][m] == MAX) f[m][m] = -1; //无法到达
cout << f[m][m] << endl;
return 0;
}
T4
正解是二分答案 + DP + 单调队列优化
先看框架
typedef long long LL;
#define MIN -9999999999
struct Data {
LL pos;
LL value;
} A[500010];
LL N, D, K;
LL DP[500010];
inline LL max(LL a, LL b) {
return (a > b) ? a : b;
}
int main() {
LL sum = 0;
scanf("%lld%lld%lld", &N, &D, &K);
for(LL i=1; i<=N; i++) {
scanf("%lld%lld", &A[i].pos, &A[i].value);
if(A[i].value > 0) sum += A[i].value;
}
if(sum < K) {
printf("-1\n");
return 0;
}
LL l = 0, r = A[N].pos, mid, ans;
while(l <= r) {
mid = (l + r) / 2;
if(Check(mid)) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%lld\n", ans);
return 0;
}
二分 + DP的Check函数(50分)
DP的思路是:循环j找到之前可以跳到这个格子的点,找到最大的DP_j,则DP_i = DP_j + 获得的分数(A[i].value)
找不到,则DP_i = -1。
bool Check_Without_Queue(LL m) {
LL mind = max(1, D-m), maxd = D + m;
LL ans = 0;
memset(DP, 0, sizeof(DP));
for(LL i=1; i<=N; i++) {
LL mx = 0, k = -1;
for(LL j=i-1; j>=0; j--) {
if(A[i].pos - A[j].pos > maxd) break;
if(DP[j] != -1 && A[i].pos - A[j].pos >= mind) {
if(mx <= DP[j]) mx = DP[j], k = j;
}
}
if(k == -1) DP[i] = -1;
else DP[i] = DP[k] + A[i].value, ans = max(ans, DP[i]);
}
if(ans >= K) return true;
return false;
}
单调队列优化的思路大概是:算出最大最小弹跳距离maxd和mind。用一个Deque(双向队列),在DP 格子i之前,加入距离>=mind的点。注意,这里的加入是加入单调队列,因此那些不优的点(DP值小的)应该剔除之后再加入队尾。下一步,从队首剔除>maxd的点,因为如果格子i跳不到,后面的格子i+1,i+2..一定还是跳不到,距离在不断变大。然后进行状态转移。
【Code】连着AC程序一块给了
#include
#include
#include
#include
using namespace std;
typedef long long LL;
#define MIN -9999999999
struct Data {
LL pos;
LL value;
} A[500010];
LL N, D, K;
LL DP[500010];
deque Q;
inline LL max(LL a, LL b) {
return (a > b) ? a : b;
}
bool Check(LL m) {
while(!Q.empty()) Q.pop_back();
memset(DP, 0, sizeof(DP));
LL mind = max(1, D-m), maxd = D+m;
LL now = 0;
A[0].pos = 0;
for(LL i=1; i<=N; i++) {
for(;now= mind; now++) {
while(!Q.empty() && DP[now] >= DP[Q.back()]) Q.pop_back();
if(DP[now] != -1) Q.push_back(now);
}
while(!Q.empty() && A[i].pos - A[Q.front()].pos > maxd) Q.pop_front();
DP[i] = Q.empty() ? -1 : DP[Q.front()] + A[i].value;
if(DP[i] >= K) return true;
}
return false;
}
int main() {
LL sum = 0;
scanf("%lld%lld%lld", &N, &D, &K);
for(LL i=1; i<=N; i++) {
scanf("%lld%lld", &A[i].pos, &A[i].value);
if(A[i].value > 0) sum += A[i].value;
}
if(sum < K) {
printf("-1\n");
return 0;
}
LL l = 0, r = A[N].pos, mid, ans = -1;
while(l <= r) {
mid = l+r >> 1;
if(Check(mid)) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%lld\n", ans);
return 0;
}