计蒜客2015 初赛题解及代码
2016-06-14 23:04
323 查看
2015 计蒜客初赛题解之工作区的颜值选择
标签(空格分隔): ACM—题解思路
简单数据 暴力代码
#include <iostream> #include <cstdio> using namespace std; const int Maxn = 2, Maxm = 3; int C[Maxn][Maxm], U[Maxn][Maxm], W[Maxn][Maxm]; int n, m, k; inline int abs(int x) { return x < 0 ? -x : x; } inline int cost(int c, int i, int j) { return (abs(c + i + j + 2) ^ U[i][j]) * W[i][j]; } int dirx[] = {-1, 0, 1, 0}; int diry[] = {0, -1, 0, 1}; int optimize(int x, int y) { if (y >= m) return 0; if (x >= n) return optimize(x ^ 1, y + 1); int best = -1; for (int i = -k; i <= k; ++i) { int tmp = cost(i,x, y); for (int l = 0; l < 4; ++l) { int nx = dirx[l] + x; int ny = diry[l] + y; if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue; tmp += abs(i + C[nx][ny]); } if (best == -1 || tmp < best) best = tmp; } return best + optimize(x ^ 1, y + 1); } int solve(int x, int y) { if (y >= m) return optimize(1, 0); if (x >= n) return solve(x ^ 1, y + 1); int ans = -1; for (int i = -k; i <= k; ++i) { C[x][y] = i; if (ans == -1) ans = solve(x ^ 1, y + 1) + cost(i, x, y); else ans = min(ans, solve(x ^ 1, y + 1) + cost(i, x, y)); } return ans; } int main(){ scanf("%d %d %d", &n, &m, &k); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &U[i][j]); } } for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &W[i][j]); } } printf("%d\n", solve(0, 0)); return 0; }
中等数据 动态规划代码(题目范围出错 n可以等于1)
#include <iostream> #include <cstdio> using namespace std; const int Maxn = 2, Maxm = 33, Maxk=33, INF = 0x7FFFFFFF; int U[Maxn][Maxm], W[Maxn][Maxm]; int n, m, k; inline int abs(int x) { return x < 0 ? -x : x; } inline int cost(int c, int i, int j) { return (abs(c + i + j + 2) ^ U[i][j]) * W[i][j]; } inline int ID(int x) { return x + Maxk; } int dp[Maxm][Maxk << 1][Maxk << 1]; int neg_decision[Maxm][Maxk << 1][Maxk << 1]; int pos_decision[Maxm][Maxk << 1][Maxk << 1]; int solve() { for (int i = -k; i <= k; ++i) { for (int j = -k; j <= k; ++j) { dp[0][ID(i)][ID(j)] = cost(i, 0, 0) + cost(j, 1, 0) + abs(i + j); } int neg = -k; int pos = k; for (int j = -k; j <= k; ++j) { if (dp[0][ID(i)][ID(j)] - j < dp[0][ID(i)][ID(neg)] - neg) neg_decision[0][ID(i)][ID(j)] = j; else neg_decision[0][ID(i)][ID(j)] = neg; if (dp[0][ID(i)][ID(-j)] - j < dp[0][ID(i)][ID(pos)] + pos) pos_decision[0][ID(i)][ID(-j)] = -j; else pos_decision[0][ID(i)][ID(-j)] = pos; neg = neg_decision[0][ID(i)][ID(j)]; pos = pos_decision[0][ID(i)][ID(-j)]; } } for (int t = 1; t < m; ++t) { for (int i = -k; i <= k; ++i) { for (int j = -k; j <= k; ++j){ int& tmp = dp[t][ID(i)][ID(j)]; tmp = INF; for (int l = -k; l <= k; ++l) { int _neg = neg_decision[t - 1][ID(l)][ID(-j)]; int _pos = pos_decision[t - 1][ID(l)][ID(-j)]; tmp = min(dp[t - 1][ID(l)][ID(_neg)] - _neg - j + abs(l + i), tmp); tmp = min(dp[t - 1][ID(l)][ID(_pos)] + _pos + j + abs(l + i), tmp); } tmp += abs(i + j) + cost(i, 0, t) + cost(j, 1, t); } int neg = -k; int pos = k; for (int j = -k; j <= k; ++j){ if (dp[t][ID(i)][ID(j)] - j < dp[t][ID(i)][ID(neg)] - neg) neg_decision[t][ID(i)][ID(j)] = j; else neg_decision[t][ID(i)][ID(j)] = neg; if (dp[t][ID(i)][ID(-j)] - j < dp[t][ID(i)][ID(pos)] + pos) pos_decision[t][ID(i)][ID(-j)] = -j; else pos_decision[t][ID(i)][ID(-j)] = pos; neg = neg_decision[t][ID(i)][ID(j)]; pos = pos_decision[t][ID(i)][ID(-j)]; } } } int ans = INF; for (int i = -k; i <= k; ++i) for (int j = -k; j <= k; ++j) ans = min(ans, dp[m - 1][ID(i)][ID(j)]); return ans; } int dp1[Maxm][Maxk << 1]; int solve_n_1() { for (int i = -k; i <= k; ++i) dp1[0][ID(i)] = cost(i, 0, 0); for (int t = 1; t < m; ++t) { for (int i = -k; i <= k; ++i) { dp1[t][ID(i)] = INF; for (int j = -k; j <= k; ++j) { dp1[t][ID(i)] = min(dp1[t][ID(i)], dp1[t - 1][ID(j)] + abs(i + j) + cost(i, 0, t)); } } } int ans = INF; for (int i = -k; i <= k; ++i) ans = min(ans, dp1[m - 1][ID(i)]); return ans; } int main(){ scanf("%d %d %d", &n, &m, &k); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &U[i][j]); } } for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &W[i][j]); } } if (n == 1) printf("%d\n", solve_n_1()); else printf("%d\n", solve()); return 0; }
困难数据 网络流代码
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 100000, INF = (1 << 30) - 1; const int Maxn = 33, Maxm = 33, Maxk=33; int U[Maxn][Maxm], W[Maxn][Maxm]; int n, m, k; inline int abs(int x) { return x < 0 ? -x : x; } inline int cost(int c, int i, int j) { return (abs(c + i + j + 2) ^ U[i][j]) * W[i][j]; } struct Edge { int to, f, next; Edge(){} Edge(int to, int f, int next): to(to), f(f), next(next){} }edge[MAXN * 4]; int box[MAXN], size; void add(int from, int to, int f){ edge[size] = Edge(to, f, box[from]); box[from] = size++; } int deep[MAXN],depnum[MAXN];// depnum记录各个距离的个数 bool isEnd; int s,t,N; void bfs()//反向分层 { memset(deep,-1,sizeof(deep)); memset(depnum,0,sizeof(depnum)); deep[t]=0; depnum[0]++; int que[MAXN],in=0,out=0; que[in++]=t; while(in>out) { int x=que[out++]; for(int i=box[x];i!=-1;i=edge[i].next) { int x1=edge[i].to; if(edge[i^1].f==0||deep[x1]!=-1)continue; que[in++]=x1; deep[x1]=deep[x]+1; depnum[deep[x1]]++; } } if(deep[s]==-1) isEnd=true; else isEnd=false; } int dfs(int x,int flow) { if(x==t)return flow; if(isEnd||flow==0)return 0; int tmp=0; int min1=deep[x]+1; for(int i=box[x];i!=-1;i=edge[i].next) { int x1=edge[i].to; if(edge[i].f==0||deep[x1]==N||deep[x1]==-1)continue; if(deep[x1]==deep[x]-1)//如果有有效路径则更新下一结点 { int tmp1=dfs(x1,min(edge[i].f,flow-tmp)); edge[i].f-=tmp1; edge[i^1].f+=tmp1; tmp+=tmp1; } if(edge[i].f)min1=min(min1,deep[x1]+1); } depnum[min1]++; depnum[deep[x]]--; if(depnum[deep[x]]==0)isEnd=true; deep[x]=min1; return tmp; } int sap() { //N=n+2; //s=n,t=n+1; int ans=0; bfs(); while(deep[s]<N&&!isEnd) { ans+=dfs(s,INF); } return ans; } int solve() { memset(box, -1, sizeof(box)); size = 0; s = 0; t = (2 * k + 2) * n * m + 1; int id = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { int first = id * (2 * k + 2) + 1; int last = first + 2 * k + 1; for (int l = first; l < last; ++l) { add(l, l + 1, cost(-k + l - first, i, j)); add(l + 1, l, cost(-k + l - first, i, j)); } if ((i + j) & 1) swap(first, last); add(s, first, INF); add(first, s, 0); add(last, t, INF); add(t, last, 0); id++; } } for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { int cur = (i * m + j) * (2 * k + 2) + 1; if (j) { int left = (i * m + j - 1) * (2 * k + 2) + 1; for (int l = 0; l < 2 * k + 2; ++l) { add (left + 2 * k + 1 - l, cur + l, 1); add (cur + l, left + 2 * k + 1 - l, 1); } } if (i) { int up = ((i - 1) * m + j) * (2 * k + 2) + 1; for (int l = 0; l < 2 * k + 2; ++l) { add (up + 2 * k + 1 - l, cur + l, 1); add (cur + l, up + 2 * k + 1 - l, 1); } } } } N = t + 1; return sap(); } int main(){ scanf("%d %d %d", &n, &m, &k); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &U[i][j]); } } for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &W[i][j]); } } printf("%d\n", solve()); return 0; }
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- C语言练习题:自由落体的小球简单实例
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中进制知识汇总
- C语言判断一个数是否是2的幂次方或4的幂次方
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- C语言实现选择排序、冒泡排序和快速排序的代码示例