给定一个
首先不难想到每一行或一列最多进行一次反转操作,否则是无用的。发现只能向右或向下,则无后效性,故可以尝试 DP。
设
我们设当前状态为
对于向右走的下一步也同理可得。
初始值即为
最终答案即为
xxxxxxxxxx71123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
22template < typename T = int >23inline T read(void);24
25int H, W;26ll R[2100], C[2100];27ll dp[2100][2100][2][2];28bitset < 2100 > G[2100];29
30int main(){31 H = read(), W = read();32 for(int i = 1; i <= H; ++i)R[i] = read();33 for(int i = 1; i <= W; ++i)C[i] = read();34 for(int i = 1; i <= H; ++i)35 for(int j = 1; j <= W; ++j){36 char c = getchar(); while(!isdigit(c))c = getchar();37 G[i][j] = c == '1' ? true : false;38 }39 memset(dp, 0x3f, sizeof dp);40 dp[1][1][0][0] = 0, dp[1][1][1][0] = R[1], dp[1][1][0][1] = C[1], dp[1][1][1][1] = R[1] + C[1];41 for(int i = 1; i <= H; ++i)42 for(int j = 1; j <= W; ++j)43 for(int x = 0; x <= 1; ++x)44 for(int y = 0; y <= 1; ++y){45 if((G[i][j] ^ x ^ y )== (G[i + 1][j] ^ y))dp[i + 1][j][0][y] = min(dp[i + 1][j][0][y], dp[i][j][x][y]);46 else dp[i + 1][j][1][y] = min(dp[i + 1][j][1][y], dp[i][j][x][y] + R[i + 1]);47 if((G[i][j] ^ x ^ y) == (G[i][j + 1] ^ x))dp[i][j + 1][x][0] = min(dp[i][j + 1][x][0], dp[i][j][x][y]);48 else dp[i][j + 1][x][1] = min(dp[i][j + 1][x][1], dp[i][j][x][y] + C[j + 1]);49 }50 ll ans(LONG_LONG_MAX);51 for(int x = 0; x <= 1; ++x)for(int y = 0; y <= 1; ++y)ans = min(ans, dp[H][W][x][y]);52 printf("%lld\n", ans);53 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);54 return 0;55}56
57template < typename T >58inline T read(void){59 T ret(0);60 int flag(1);61 char c = getchar();62 while(c != '-' && !isdigit(c))c = getchar();63 if(c == '-')flag = -1, c = getchar();64 while(isdigit(c)){65 ret *= 10;66 ret += int(c - '0');67 c = getchar();68 }69 ret *= flag;70 return ret;71}update-2023_01_03 初稿