社区讨论
这题怎么卡常啊/ll
CF2097FLost Luggage参与者 3已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mkcedocs
- 此快照首次捕获于
- 2026/01/13 17:36 上个月
- 此快照最后确认于
- 2026/01/17 10:45 上个月
根据第一篇题解写的 dp,状态数已经 了,转移的时候还要枚举 次来判断三条边是否割掉,这咋卡常啊/yun
CPP#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
auto IOS = ios::sync_with_stdio(false);
auto CIN = cin.tie(nullptr);
int mread(){
int x = 0, f = 1;
char c = cin.get();
while(c < '0' || c > '9'){
if(c == '-'){
f = -1;
}
c = cin.get();
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = cin.get();
}
return x * f;
}
const int N = 3005;
const int inf = 1200000000;
int t = mread(), a[N][20], b[N][20], c[N][20], s[20];
int tmp[N][20][8], nxt[2048][20][8];
// 第一维表示天数,滚动,第二维表示状态,第三维表示当前应该考虑哪个点,为 0 则代表考虑完了,第四维表示 n - 1 是否被迫联通,第五维代表即将考虑的点是否被迫联通
int f[2][2048][13][2][2];
void get(int &x, int y){
if(y < x){
x = y;
}
return;
}
signed main(){
while(t --){
int n = mread(), m = mread();
for(int i = 0; i < n; i ++){
s[i] = mread();
}
for(int i = 1; i <= m; i ++){
for(int j = 0; j < n; j ++){
a[i][j] = mread();
}
for(int j = 0; j < n; j ++){
b[i][j] = mread();
}
for(int j = 0; j < n; j ++){
c[i][j] = mread();
}
}
int ma = 1 << n;
for(int i = 0; i < 2; i ++){
for(int j = 0; j < ma; j ++){
for(int k = 0; k <= n; k ++){
for(int l = 0; l < 4; l ++){
f[i][j][k][l & 1][l >> 1 & 1] = inf;
}
}
}
}
for(int now = 0; now < ma; now ++){
f[0][now][0][0][0] = 0;
for(int i = 0; i < n; i ++){
if(!(now >> i & 1)){
f[0][now][0][0][0] += s[i];
}
}
}
for(int t = 1; t <= m; t ++){
for(int i = 0; i < n; i ++){
for(int vt = 0; vt < 8; vt ++){
tmp[t][i][vt] = 0;
if(vt >> 0 & 1){
tmp[t][i][vt] += a[t][i];
}
if(vt >> 1 & 1){
tmp[t][i][vt] += b[t][i];
}
if(vt >> 2 & 1){
tmp[t][i][vt] += c[t][i];
}
}
}
}
for(int now = 0; now < ma; now ++){
for(int i = 1; i < n; i ++){
for(int vt = 0; vt < 8; vt ++){
nxt[now][i][vt] = now;
if(vt >> 0 & 1){
}
else{
nxt[now][i][vt] |= 1 << i - 1;
}
if(vt >> 1 & 1){
nxt[now][i][vt] -= 1 << i;
}
}
}
}
for(int now = 0; now < ma; now ++){
if(now >> 0 & 1){
for(int t = 0; t < 8; t ++){
int nxt = now;
int t0 = 1, t2 = 1;
int tmp = f[0][now][0][0][0];
if(t >> 0 & 1){
t0 = 0, tmp += a[1][0];
}
if(t >> 1 & 1){
nxt -= 1, tmp += b[1][0];
}
if(t >> 2 & 1){
t2 = 0, tmp += c[1][0];
}
get(f[1][nxt][1][t0][t2], tmp);
}
}
else{
get(f[1][now][1][0][0], f[0][now][0][0][0]);
}
f[0][now][0][0][0] = inf;
}
for(int t = 1; t <= m; t ++){
for(int i = 1; i < n; i ++){
for(int now = 0; now < ma; now ++){
for(int t0 = 0; t0 <= 1; t0 ++){
for(int t2 = 0; t2 <= 1; t2 ++){
if(f[t & 1][now][i][t0][t2] == inf){
continue;
}
// printf("*** %d %d %d %d %d %intd\n", t, now, i, t0, t2, f[t & 1][now][i][t0][t2]);
if(now >> i & 1){
for(int vt = 0; vt < 8; vt ++){
get(f[t & 1][nxt[now][i][vt] | (t2 << i)][i + 1][t0][!(vt >> 2 & 1)], f[t & 1][now][i][t0][t2] + tmp[t][i][vt]);
}
}
else{
get(f[t & 1][now | (t2 << i)][i + 1][t0][0], f[t & 1][now][i][t0][t2]);
}
f[t & 1][now][i][t0][t2] = inf;
}
}
}
}
for(int now = 0; now < ma; now ++){
for(int t0 = 0; t0 <= 1; t0 ++){
for(int t2 = 0; t2 <= 1; t2 ++){
get(f[t & 1][now | (t0 << n - 1) | t2][0][0][0], f[t & 1][now][n][t0][t2]);
f[t & 1][now][n][t0][t2] = inf;
}
}
}
cout << f[t & 1][0][0][0][0] << "\n";
if(t == m){
break;
}
for(int now = 0; now < ma; now ++){
if(now >> 0 & 1){
for(int vt = 0; vt < 8; vt ++){
int nxt = now;
int vt2 = 1, vt0 = 1;
int tmp = f[t & 1][now][0][0][0];
if(vt >> 0 & 1){
vt0 = 0, tmp += a[t + 1][0];
}
if(vt >> 1 & 1){
nxt -= 1, tmp += b[t + 1][0];
}
if(vt >> 2 & 1){
vt2 = 0, tmp += c[t + 1][0];
}
get(f[t + 1 & 1][nxt][1][vt0][vt2], tmp);
}
}
else{
get(f[t + 1 & 1][now][1][0][0], f[t & 1][now][0][0][0]);
}
f[t & 1][now][0][0][0] = inf;
}
}
}
return 0;
}
回复
共 3 条回复,欢迎继续交流。
正在加载回复...