UVA - 10558 A Brief Gerrymander 很抽象的题目
来源:互联网 发布:带着空间去民国淘宝 编辑:程序博客网 时间:2024/04/30 10:29
题目大意:把城市看成一个棋盘,点看成棋子。那么题意就比较好理解了。有一个坐标为1-100的正方形棋盘,在这个正方形上有N个棋子,然后有M个数,表示沿着这个棋盘的M条竖线各切了1刀,将其划分成了M-1个块,这M条竖线中必包含有1和100。现在要求你再将其划分,这次是按横线划分,要求划A次,A次中必要包含1和100,划分完后,将其分解成一个个小矩形,要求含有棋子的矩形数目达到最大
解题思路:预处理比较难,再还没有横着切之前,先判断以下每一块的每一行是否有棋子,因为是按横线划分的,且只要求包含有棋子,所以在同一块中,横线上有多少的棋子就不重要了,然后再判断一下,同一块中从第0行到第i行能划分成几个块,能划分成几个块表示的是有几行有棋子,这是一个闭区间[0,i],最后再统计一下第i行到第j行能划分成几块,这是个左闭右开的区间[i,j),就是统计一下每一块的第[i,j)区间内能被划分成几块,然后再进行相加,这样预处理就好了。
接着是转换公式了:dp[i][j] = max(dp[i][j],dp[k][j-1] + s[i][k]),dp[i][j]表示从区间(i,100)划分j次的最优解,具体的解析请看点击打开链接
我代码中也有注解。
#include<cstdio>#include<cstring>#define maxn 110bool vis[maxn][maxn],judge[maxn][maxn],g[maxn][maxn];int dp[maxn][maxn],s[maxn][maxn],f[maxn][maxn],a[maxn],path[maxn][maxn];int N,A,S;void init() {memset(g,0,sizeof(g));memset(vis,0,sizeof(vis));memset(f,0,sizeof(f));int t1,t2;for(int i = 0; i < N; i++) {scanf("%d%d",&t1,&t2);g[t2][t1] = 1;}scanf("%d",&S);for(int i = 1; i <= S; i++)scanf("%d",&a[i]);//judge[i][k]是判断第k块第i行是否有符合的点,f[i][k]是记录第k块从第0行到第i行可以划分成几个区,区间是[0,i],闭区间scanf("%d",&A);for(int k = 1; k < S; k++) for(int i = 1; i < 100; i++) {judge[i][k] = f[i][k] = 0;for(int j = a[k]; j < a[k+1]; j++)if(g[i][j] == 1) {judge[i][k] = 1;break;}f[i][k] = judge[i][k];f[i][k] += f[i-1][k];}//s[i][j]记录的是从第i行到第j行有几个区,区间是[i,j),左闭右开的for(int i = 1; i < 100; i++)for(int j = i + 1; j <= 100; j++) {s[i][j] = 0;for(int k = 1; k < S; k++)if(f[j-1][k] - f[i][k] + judge[i][k])s[i][j]++;}}int DP(int i,int j) {int k, ans;if(vis[i][j])return dp[i][j];if(j == 0)return dp[i][j] = s[i][100];vis[i][j] = 1;dp[i][j] = 0;//dp[i][j]表示从(i,100)中划分j次,转移方程为dp[i][j] = max(dp[k][j-1]+s[i][k],dp[i][j]),相当于把第k条线当成了划分线了,就是说上一块的区间是[i,k),还要判断从(k,100)是否还能够划分,能被当成划分的线只剩下100-k-1条了(排除了第k条和第100条),还需要划分j-1次,所以当100-k-1 < j - 1时,就表示不能被划分了,break掉for(k = i + 1; k < 100; k++) {if(100 - k - 1 < j -1)break;ans = DP(k,j-1);if(s[i][k] + ans > dp[i][j]) {dp[i][j] = s[i][k] + ans;path[i][j] = k;}}return dp[i][j];}void print_path(int i,int j) {int k;if(j <= 0)return ;k = path[i][j];printf(" %d",k);print_path(k,j-1);return ;}int main() {while(scanf("%d",&N) != EOF && N != -1) {init();DP(1,A-2);printf("%d",A);printf(" 1");print_path(1,A-2);printf(" 100\n");}return 0;}
0 0
- UVA - 10558 A Brief Gerrymander 很抽象的题目
- UVA - 10558 A Brief Gerrymander
- uva 10558 - A Brief Gerrymander
- UVA - 10558 A Brief Gerrymander
- uva 10558 - A Brief Gerrymander(记忆化搜索)
- uva 10558 A Brief Gerrymander (dp记忆化搜索)
- UVA - 10558A Brief Gerrymander(递推)
- uva 10558 - A Brief Gerrymander (dp之不好理解的题意)
- UVA10558- A Brief Gerrymander
- A brief advice
- A brief on using CreateRemoteThread
- A Brief Introduction to IoC
- A Brief Introduction to IoC
- A Brief Introduction to REST
- A Brief Introduction to REST
- Analytical Functions: A Brief Introduction
- A Brief Introduction to OVF
- A Brief Introduction to Myself
- 第288天(30W+4)(29W+6)
- 帆船驾驶技术的物理学原理
- windows下QT环境的搭建:Qt(library)4.8.6+MinGW+Qtcreator3.2
- Android系统中使用Console命令播放视频文件
- C++11 并发指南二(std::thread 详解)
- UVA - 10558 A Brief Gerrymander 很抽象的题目
- 检查运行更改代码后的程序
- getchar()与putchar()概念及相关用法
- web.py 十分钟创建简易博客
- usb驱动学习笔记
- 详细叙述各常见数据类型所占字节
- 人生两大选择:要么接受现状,要么接受改变现状的责任
- ceph存储 关于OpenStack与Ceph集成的若干参考
- 【DP|01背包】HDU-2955 Robberies