【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏
来源:互联网 发布:mysql存储过程模板 编辑:程序博客网 时间:2024/05/05 06:29
题目描述
流行的跳棋游戏是在一个有m*n个方格的长方形棋盘上玩的。棋盘起初全部被动物或障碍物占满了。在一个方格中,‘X’表示一个障碍物,一个‘0’~‘9’的个位数字表示一个不同种类的动物,相同的个位数字表示相同种类的动物。一对动物只有当它们属于同一种类时才可以被消去。消去之后,他们所占的方格就成为空方格,直到游戏结束。要消去一对动物的前提条件是:这对候选动物所在的方格必须相邻,或它们之间存在一条通路。棋盘上一个方格只和其上下左右的方格相邻。一条通路是由一串相邻的空方格组成。路的长度则是通路中空方格的数目。你要输出可被消去的动物的最多对数,以及在此操作过程中,最小的通路长度总和。
数据范围
N,M<=5
解法
暴力+剪枝
正确性可以保证,时间效率较低;
可以考虑牺牲点正确性以提高时间效率。
A*
正确性和时间效率取决于估价函数。
带策略的暴力
正确性勉强,时间效率卡常数;
贪心
正确性无法保证,时间效率高;
所以可以考虑牺牲时间效率,多次求解求最优。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;const char* fin="pair.in";const char* fout="pair.out";const int inf=0x7fffffff;const int maxn=13,maxm=maxn*maxn;const int h[4][2]={{1,0},{-1,0},{0,1},{0,-1}};int n,m,i,j,k,maxx,ans1,ans2,interesting=5,hx,hy,ans3,ans4;char a[maxn][maxn];bool bz[maxn][maxn];int b[maxm][2],head,tail,c[6];int f[maxn][maxn];int heavy(int x,int y){ return max(abs(x-hx),abs(y-hy));}void add(int x,int y,int z,int awful){ if (z>=f[x][y] || (!bz[x][y] && awful==0) || a[x][y]=='X') return ; b[++tail][0]=x; b[tail][1]=y; f[x][y]=z;}int getdis(int x,int y,int u,int v){ int i,j,k,ans=inf; memset(f,127,sizeof(f)); head=tail=0; add(x,y,0,1); while (head++<tail){ for (i=0;i<4;i++){ j=b[head][0]+h[i][0]; k=b[head][1]+h[i][1]; if (j>0 && j<=n && k>0 && k<=m) if (j==u && k==v) ans=min(f[b[head][0]][b[head][1]],ans); else add(j,k,f[b[head][0]][b[head][1]]+1,0); } } return ans;}void work(int x,int y){ int i,j,k,minx=10000,mnid[2],mminx=inf; for (i=1;i<=n;i++) for (j=1;j<=m;j++) if (!bz[i][j] && a[i][j]==a[x][y]){ if (x==i && y==j) continue; k=getdis(x,y,i,j); if (k<minx || k==minx && heavy(i,j)<mminx){ minx=k; mminx=heavy(i,j); mnid[0]=i; mnid[1]=j; } } if (minx==10000) return; else{ /*ans1++; ans2+=minx; bz[x][y]=true; bz[mnid[0]][mnid[1]]=true;*/ if (c[1]>minx){ c[1]=minx; c[2]=x; c[3]=y; c[4]=mnid[0]; c[5]=mnid[1]; } }}void solve(int v){ int i,j,k; while (1){ c[1]=10000; for (i=v;i<=n-v+1;i++) if (!bz[i][m-v+1] && a[i][m-v+1]!='X') work(i,m-v+1); for (i=m-v+1;i>=v;i--) if (!bz[i][v] && a[i][v]!='X') work(i,v); for (i=v;i<=n-v+1;i++) if (!bz[n-v+1][i] && a[n-v+1][i]!='X') work(n-v+1,i); for (i=m-v+1;i>=v;i--) if (!bz[v][i] && a[v][i]!='X') work(v,i); if (c[1]<10000){ bz[c[2]][c[3]]=true; bz[c[4]][c[5]]=true; ans1++; ans2+=c[1]; }else break; }}int main(){ freopen(fin,"r",stdin); freopen(fout,"w",stdout); scanf("%d%d",&n,&m); for (i=1;i<=n;i++) scanf("%s",a[i]+1); maxx=min((n+1)/2,(m+1)/2); for (hx=1;hx<=n;hx++) for (hy=1;hy<=m;hy++){ memset(bz,0,sizeof(bz)); ans1=ans2=0; for (i=1;i<=maxx;i++){ for (j=i;j;j--){ solve(j); } } if (ans1>ans3 || ans1==ans3 && ans2<ans4){ ans3=ans1; ans4=ans2; } } for (hx=1;hx<=n;hx++) for (hy=1;hy<=m;hy++){ memset(bz,0,sizeof(bz)); ans1=ans2=0; for (i=maxx;i;i--){ for (j=i;j;j--){ solve(j); } } if (ans1>ans3 || ans1==ans3 && ans2<ans4){ ans3=ans1; ans4=ans2; } } for (hx=1;hx<=n;hx++) for (hy=1;hy<=m;hy++){ memset(bz,0,sizeof(bz)); ans1=ans2=0; for (i=maxx;i;i--){ for (j=1;j<=maxx;j++){ solve(j); } } if (ans1>ans3 || ans1==ans3 && ans2<ans4){ ans3=ans1; ans4=ans2; } } for (hx=1;hx<=n;hx++) for (hy=1;hy<=m;hy++){ memset(bz,0,sizeof(bz)); ans1=ans2=0; for (i=1;i<=maxx;i++){ for (j=i;j;j--){ solve(j); } } if (ans1>ans3 || ans1==ans3 && ans2<ans4){ ans3=ans1; ans4=ans2; } } printf("%d %d",ans3,ans4); return 0;}
启发
这种题常出现在NOIP提高组的压轴题,
往往没有稳定复杂度的算法。
此时就要考虑上述几种做法,进行取舍,以骗得最高的分数。
大致上就是平衡时间效率和正确性。
此外还有考虑编程复杂度的问题,以我的观点:
贪心的编程复杂度最简单,也最容易调试;
因为贪心的每一次操作具有后效性。
1 0
- 【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏
- NOIP2016提高A组集训第1场 【JZOJ4824】配对游戏
- 【NOIP2016提高A组集训第1场10.29】配对游戏
- JZOJ 4824. 【NOIP2016提高A组集训第1场10.29】配对游戏
- JZOJ 4823. 【NOIP2016提高A组集训第1场10.29】小W学物理
- 【NOIP2016提高A组集训第1场10.29】完美标号
- 【NOIP2016提高A组集训第1场10.29】小W学物理
- 【NOIP2016提高A组集训第1场10.29】完美标号
- JZOJ 4822. 【NOIP2016提高A组集训第1场10.29】完美标号
- JZOJ 4822. 【NOIP2016提高A组集训第1场10.29】完美标号
- JZOJ4822. 【NOIP2016提高A组集训第1场10.29】完美标号
- {题解}[jzoj4823] 【NOIP2016提高A组集训第1场10.29】小W学物理
- {题解}[jzoj4823] 【NOIP2016提高A组集训第1场10.29】小W学物理
- JZOJ4822. 【NOIP2016提高A组集训第1场10.29】完美标号
- JZOJ4823. 【NOIP2016提高A组集训第1场10.29】小W学物理
- 【NOIP2016提高A组集训第1场10.29】完美标号
- 【NOIP2016提高A组集训第1场10.29】小W学物理
- 完美标号【NOIP2016提高A组集训第1场10.29】
- android 微信分享出去的图片不显示或显示成应用图标
- July15th 回家【推荐】Go home 题解
- 触摸屏拓展屏软件(可自定义界面)
- hdu 5935 Car【贪心】
- hdu4533
- 【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏
- java内部类的初始化
- 第9周OJ实践 ASCII码排序
- 高精压位 操作符重载
- 进程、线程与多线程
- Java数组
- iOS -开发中的HTTPS
- 【转载】DPDK编程开发(4)—lcore
- 【转载】DPDK编程开发(5)—mbuf