0430B

已结束 IOI 开始于: 2026-4-30 14:00 3.5 小时 主持人: 43
// 每一行是互不相干的,各自计算各自的值
// 区间DP,f[i][j] 代表取区间[i,j]的最大值
// 对于区间 [i,j],要么先取 a[i] , 要么先取 a[j]
// 可以理解为,我取了 a[i] , 那么接下来的区间的等级就会往上升一个等级,*2
// f[i][j] = max(2*f[i+1][j] + 2*a[i] , 2*f[i][j-1]+2*a[j])
#include<bits/stdc++.h>
using namespace std;
const int N = 90;
int n, m;
__int128 a[N], res;
__int128 f[N][N];

// 读取 __int128
__int128 read() {
	__int128 x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-') f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}

// 输出 __int128
void print(__int128 x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9) print(x / 10);
	putchar(x % 10 + '0');
}

signed main() {
	cin >> n >> m;
	while (n--) {
		for (int i = 1; i <= m; i++)
			a[i] = read();
		memset(f, 0, sizeof f);
		for (int len = 0 ; len <= m; len++) {
			for (int i = 1; i + len <= m; i++) {
				int j = i + len;
				f[i][j] = max(2 * f[i + 1][j] + 2 * a[i], 2 * f[i][j - 1] + 2 * a[j]);
			}
		}
		res += f[1][m];
	}
	print(res);
	return 0;
}
#include<bits/stdc++.h>
#define int long long
#pragma GCC Optimize(3)
using namespace std;
const int MOD = 998244353;
int num[45][45],dp[45][100005];
signed main(){
	string s; cin >> s;
	int n; cin >> n;
	int sz = s.size();
	for(int i = 1;i <= sz;i++){
		num[i][i] = s[i - 1] - '0';
		for(int j = i + 1;j <= sz;j++) num[i][j] = num[i][j - 1] * 10 + (s[j - 1] - '0');
	}
	memset(dp,0x3f3f3f3f,sizeof dp);
	dp[0][0] = -1;
	for(int i = 1;i <= sz;i++){
		for(int j = 0;j <= n;j++){
			for(int k = i - 1;k >= 0;k--){
				if(num[k + 1][i] > n) break;
				if(j >= num[k + 1][i]) dp[i][j] = min(dp[i][j],dp[k][j - num[k + 1][i]] + 1);
			}
		}
	}
	if(dp[sz][n] < 45) cout << dp[sz][n];
	else cout << -1;
	return 0;
}
f[i][j][ii][jj] 第一次走到(i, j),
第二次走到(ii, jj) 的最大值
向下走,向右走, 两个点,  2*2

向下, 向下    f[i-1][j][ii-1][j] + a[i][j] + a[ii][jj]( i!=ii || j!=jj 成立的时候加) 
向下,向右      
向右,向下
向右。向右

转移:f[i][j][ii][jj] = max(f[i])
f[i][j]  用了前 i 个字符,凑出j的最少加号个数

sum[k+1][j] 代表的是 从 k+1 到 j 这一段的和

预处理,求一下 sum

转移方程:f[i][j] = min(f[i][j] , f[k][j-sum[k+1][i]]+1)
初始化:memset(f, 0x3f , sizeof f);
f[0][0] = -1
#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
int dp[2][105][105][4];
char mp[105][105];
string op[1005];
void solve(){
    int m,n,x,y; cin >> m >> n >> x >> y;
    for(int i = 1;i <= m;i++){
        for(int j = 1;j <= m;j++) cin >> mp[i][j];
    }
    for(int i = 1;i <= n;i++) cin >> op[i];
    memset(dp,0x3f3f3f3f,sizeof dp);
    dp[0][x][y][0] = 0;
    for(int i = 1;i <= n;i++){
        for(int xx = 1;xx <= m;xx++){
            for(int yy = 1;yy <= m;yy++){
                if(mp[xx][yy] == '*') continue;
                for(int k = 0;k < 4;k++){
                    if(op[i] == "FORWARD") dp[i % 2][xx][yy][k] = min(dp[(i % 2) ^ 1][xx][yy][k] + 1,dp[(i % 2) ^ 1][xx - dir[k][0]][yy - dir[k][1]][k]);
                    else if(op[i] == "BACK") dp[i % 2][xx][yy][k] = min(dp[(i % 2) ^ 1][xx][yy][k] + 1,dp[(i % 2) ^ 1][xx + dir[k][0]][yy + dir[k][1]][k]);
                    else if(op[i] == "LEFT") dp[i % 2][xx][yy][k] = min(dp[(i % 2) ^ 1][xx][yy][k] + 1,dp[(i % 2) ^ 1][xx][yy][(k + 1) % 4]);
                    else dp[i % 2][xx][yy][k] = min(dp[(i % 2) ^ 1][xx][yy][k] + 1,dp[(i % 2) ^ 1][xx][yy][(k + 3) % 4]);
                }
            }
        }
    }
    int sum = 1e18;
    for(int i = 1;i <= m;i++){
        for(int j = 1;j <= m;j++){
            if(mp[i][j] == '*') continue;
            for(int k = 0;k < 4;k++) sum = min(sum,dp[n % 2][i][j][k]);
        }
    }
    cout << sum;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int c,T = 1;
    while(T--) solve();
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
long long n, m, a[1005][1005], f[1005][1005], ans = LLONG_MIN, vis[1005][1005], cnt,b,maxx;
stack<long long>c;
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> a[i][j];
	for (int i = 1; i <= m; i++)
		f[1][i] = a[1][i];
	for (int i = 2; i <= n; i++)
		for (int j = i; j <= m; j++) {
			b = 0, maxx = LLONG_MIN;
			for (int k = i - 1; k < j; k++)
				if (f[i - 1][k] > maxx)
					maxx = f[i - 1][k],b = k;
			f[i][j] = f[i - 1][b] + a[i][j],vis[i][j] = b;
			if (i == n)
				if (f[i][j] > ans)
					ans = f[i][j],cnt = j;
		}
	c.push(cnt);
	for (int i = n; i >= 2; i--)
		cnt = vis[i][cnt],c.push(cnt);
	cout << ans << '\n';
	while (!c.empty())
		cout << c.top() << " ",c.pop();
	return 0;
}

状态
已结束
规则
IOI
题目
6
开始于
2026-4-30 14:00
结束于
2026-4-30 17:30
持续时间
3.5 小时
主持人
参赛人数
43