uva 10558 - A Brief Gerrymander (dp之不好理解的题意)
2014-03-05 16:48
393 查看
链接:uva
10558
题意:一个棋盘,横竖线都是从1到100标号(竖线从左到右标,横线从下到上标),输入n表示有n个被标记的格子,给出这个格子的左下角坐标,然后输入m,在输入m个数,表示在这些竖线的地方切开棋盘(其实只切了m-2刀,因为2刀必须是1和100,相当于没有),然后输入A,表示你要在横上上切A刀(其实也只是A-2刀,因为2刀必须在横线的1和100)。那么就可以把棋盘很多个大小不一的方块(矩形),只要这些方块中有被标记的小格子(1个或多个),那么这个方块就是一个选区,我们是要使到选区的个数最多.(先输入列,再输入行)
思路:
预处理num[i][j]有多少个选区,然后dp。
dp[i][j] 选到 i 行切了 j 刀获得的最大选区个数。
二维纪录路径。
注意必须切 j 刀,1、100不算就是切 j-2 刀。
感想:
题意读不懂真蛋疼,一直WA真桑心,然后推荐一个比较好的uva oj board ,里面的discuss比较好。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 1005 #define MAXN 2005 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,m,ans,cnt,tot,flag; int mp[105][105],a[105][105],line[105],street[105],st[105]; int num[105][105],dp[105][105],prex[105][105]; void presolve() { int i,j,t,now; memset(a,0,sizeof(a)); for(i=1; i<=100; i++) { for(j=1; j<100;) { now=j; if(mp[i][j]) a[i][now]=1; j++; while(!line[j]) { if(mp[i][j]) a[i][now]=1; j++; } } } for(i=1; i<=100; i++) // 预处理num数组 原理同 | 运算 { memset(st,0,sizeof(st)); for(j=i+1; j<=100; j++) { for(int k=1; k<m; k++) { if(a[j-1][street[k]]) st[street[k]]=1; } t=0; for(int k=1; k<m; k++) { if(st[street[k]]) t++; } num[i][j]=t; } } } void output(int x,int y) { if(y==0) return ; output(prex[x][y],y-1); printf(" %d",x); } void solve() { int i,j,t,k1; ans=0; memset(dp,-INF,sizeof(dp)); memset(prex,-1,sizeof(prex)); tot-=2; for(i=0; i<=100; i++) dp[i][0]=0; for(i=1; i<=100; i++) { for(j=1; j<=i&&j<=tot; j++) { for(int k=1; k<i; k++) { if(dp[i][j]<dp[k][j-1]+num[k][i]) { dp[i][j]=dp[k][j-1]+num[k][i]; prex[i][j]=k; } } if(ans<dp[i][tot]+num[i][100]) // 加上最后一块的选区 { ans=dp[i][tot]+num[i][100]; k1=i; } } } printf("%d 1",tot+2); output(k1,tot); printf(" 100\n"); } int main() { int i,j,t; while(scanf("%d",&n)) { if(n==-1) break ; int x,y; memset(mp,0,sizeof(mp)); for(i=1; i<=n; i++) { scanf("%d%d",&y,&x); mp[x][y]=1; } scanf("%d",&m); memset(line,0,sizeof(line)); for(i=1; i<=m; i++) { scanf("%d",&t); street[i]=t; line[t]=1; } scanf("%d",&tot); if(tot==2) { printf("2 1 100\n"); continue ; } presolve(); solve(); } return 0; }
相关文章推荐
- uva 10558(dp)
- 存下自己尝试的代码 UVA 548 题意不理解,英语捉急。但是有收获
- ZOJ 3713 In 7-bit (题意不好理解,十进制、二进制、十六进制的转换问题)
- uva488题意的理解和空格的控制
- 理解题意后的UVa340
- UVA10300(理解题意就容易切)
- UVA - 414 Machined Surfaces(题意不好懂)
- NYOJ-269-VF(DP不好理解)
- HDU 2526 题意不好理解,用到滚动数组
- uva10558(DP)
- UVA1220树上的dp(最大独立集)
- uva 10304 - Optimal Binary Search Tree(区间dp)
- UVA 1625 Color Length (DP)
- Cross the Wall UVALive - 5097 (贪心+斜率dp)
- Uva-10934 Dropping water balloons(dp)
- UVA 6624(简单概率dp)
- UVA 11133 - Eigensequence(DP)
- UVa 1336 Fixing the Great Wall (区间DP)
- dp(uva562Dividing coins)
- UVA 10003 Cutting Sticks [线性结构dp] [最优矩阵链乘]