斗地主 && Mayan游戏 && 作业调度方案
斗地主
题目描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的AA到KK加上大小王的共5454张牌来进行的扑克牌游戏。在斗地主中,牌的大小关 系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<\text{小王}<\text{大王}3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由 nn 张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。
现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:
本题数据随机,不支持hack,要hack或强力数据请点击这里
输入输出格式
输入格式:
第一行包含用空格隔开的2个正整数 T,nT,n ,表示手牌的组数以及每组手牌的张数。
接下来 TT 组数据,每组数据 nn 行,每行一个非负整数对 a_i,b_iai,bi ,表示一张牌,其中 a_iai 表示牌的数码, b_ibi表示牌的花色,中间用空格隔开。特别的,我们用 11 来表示数码 AA, 1111 表示数码JJ, 1212 表示数码QQ, 1313 表示数码 KK;黑桃、红心、梅花、方片分别用 1-41−4 来表示;小王的表示方法为 0101 ,大王的表示方法为 0202 。
输出格式:
共 TT 行,每行一个整数,表示打光第 ii 组手牌的最少次数。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 using namespace std; 10 const int maxn=37; 11 const int INF=0x7f7f7f7f; 12 int read(){ 13 int x=0,f=1;char s=getchar(); 14 while(s<'0'||s>'9'){if(s=='-') f=-1;s=getchar();} 15 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 16 return x*f; 17 } 18 int t,n,ans; 19 int req[5]={0,5,3,2}; 20 bool flg1,flg2; 21 int a[maxn],b[maxn],dp[maxn][maxn][maxn][maxn],cnt[maxn],tot[maxn]; 22 void pre(){ 23 memset(dp,INF,sizeof(dp)); 24 dp[0][0][0][0]=0; 25 for(int i=0;i<=25;i++){ 26 for(int j=0;j<=25;j++){ 27 for(int k=0;k<=25;k++){ 28 for(int u=0;u<=25;u++){ 29 if(i>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i-1][j][k][u]+1); 30 if(j>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j-1][k][u]+1); 31 if(k>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j][k-1][u]+1); 32 if(u>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j][k][u-1]+1); 33 if(j>0&&u>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j-1][k][u-1]+1); 34 if(j>0&&k>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j-1][k-1][u]+1); 35 if(i>0&&u>1) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i-1][j][k][u-2]+1); 36 if(i>0&&k>1) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i-1][j][k-2][u]+1); 37 } 38 } 39 } 40 } 41 } 42 void san(int stp){ 43 memset(tot,0,sizeof(tot)); 44 for(int i=1;i<=12;i++){ 45 tot[cnt[i]]++; 46 }tot[cnt[13]]++; 47 if(flg1==true&&flg2==true){ 48 ans=min(ans,min(dp[tot[4]][tot[3]][tot[2]][tot[1]]+1,dp[tot[4]][tot[3]][tot[2]][tot[1]+2])+stp); 49 } 50 else if((flg1==true&&flg2==false)||(flg1==false&&flg2==true)){ 51 ans=min(ans,dp[tot[4]][tot[3]][tot[2]][tot[1]+1]+stp); 52 } 53 else{ 54 ans=min(ans,dp[tot[4]][tot[3]][tot[2]][tot[1]]+stp); 55 }//? 56 57 /*for(int i=1;i<=3;i++){ 58 int tou=1,wei=0; 59 for(int j=1;j<=12;j++){ 60 if(cnt[j]>=i) wei++; 61 else{ 62 if(wei-tou+1>=req[i]){ 63 for(int k=tou;k<=wei;k++) cnt[k]-=i; 64 san(stp+1); 65 for(int k=tou;k<=wei;k++) cnt[k]+=i; 66 } 67 wei++;tou=wei+1; 68 } 69 } 70 if(tou!=wei&&wei==12&&wei-tou+1>=req[i]){ 71 for(int k=tou;k<=wei;k++) cnt[k]-=i; 72 san(stp+1); 73 for(int k=tou;k<=wei;k++) cnt[k]+=i; 74 }//? 75 }*/ 76 //有可能是一段连续的,但是从后面截取一段会更优 77 int len=0; 78 for(int i=1;i<=12;i++){ 79 if(cnt[i]<1) len=0; 80 else{ 81 len++; 82 if(len>=5){ 83 int tmp=len; 84 while(tmp>=5){ 85 for(int j=i;j>=i-tmp+1;j--) cnt[j]--; 86 san(stp+1); 87 for(int j=i;j>=i-tmp+1;j--) cnt[j]++; 88 tmp--; 89 } 90 } 91 } 92 } 93 len=0; 94 for(int i=1;i<=12;i++){ 95 if(cnt[i]<2) len=0; 96 else{ 97 len++; 98 if(len>=3){ 99 int tmp=len; 100 while(tmp>=3){ 101 for(int j=i;j>=i-tmp+1;j--) cnt[j]-=2; 102 san(stp+1); 103 for(int j=i;j>=i-tmp+1;j--) cnt[j]+=2; 104 tmp--; 105 } 106 } 107 } 108 } 109 len=0; 110 for(int i=1;i<=12;i++){ 111 if(cnt[i]<3) len=0; 112 else{ 113 len++; 114 if(len>=2){ 115 int tmp=len; 116 while(tmp>=2){ 117 for(int j=i;j>=i-tmp+1;j--) cnt[j]-=3; 118 san(stp+1); 119 for(int j=i;j>=i-tmp+1;j--) cnt[j]+=3; 120 tmp--; 121 } 122 } 123 } 124 } 125 } 126 int main(){ 127 t=read();n=read(); 128 pre(); 129 while(t--){ 130 memset(a,0,sizeof(a));memset(b,0,sizeof(b)); 131 memset(cnt,0,sizeof(cnt));memset(tot,0,sizeof(tot)); 132 flg1=false;flg2=false;ans=INF; 133 for(int i=1;i<=n;i++){ 134 a[i]=read();b[i]=read(); 135 if(a[i]>=3) a[i]-=2; 136 else if(a[i]>=1&&a[i]<=2) a[i]+=11; 137 else if(a[i]==0){ 138 if(b[i]==1) {a[i]=14;flg1=true;} 139 if(b[i]==2) {a[i]=15;flg2=true;} 140 }//注意第二个要打else 141 cnt[a[i]]++; 142 } 143 san(0); 144 printf("%d\n",ans); 145 } 146 return 0; 147 }
Mayan游戏
题目描述
Mayan puzzle
是最近流行起来的一个游戏。游戏界面是一个77 行\times 5×5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:
1 、每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参见输入输出样例说明中的图66到图77 );如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图1 和图2);
2 、任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除(参见图1 到图3)。
注意:
a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如下面图44 ,三个颜色为11 的方块和三个颜色为 22 的方块会同时被消除,最后剩下一个颜色为22的方块)。
b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除(例如下面图5 所示的情形,5 个方块会同时被消除)。
3 、方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除。
上面图1 到图 3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐标为(0, 0 ),将位于(3, 3 )的方块向左移动之后,游戏界面从图 1 变成图 2 所示的状态,此时在一竖列上有连续三块颜色为4 的方块,满足消除条件,消除连续3 块颜色为4 的方块后,上方的颜色为3 的方块掉落,形成图 3 所示的局面。
输入输出格式
输入格式:
共 6 行。
第一行为一个正整数n,表示要求游戏通关的步数。
接下来的5行,描述7×5 的游戏界面。每行若干个整数,每两个整数之间用一个空格隔开,每行以一个0 结束,自下向上表示每竖列方块的颜色编号(颜色不多于10种,从1开始顺序编号,相同数字表示相同颜色)。
输入数据保证初始棋盘中没有可以消除的方块。
输出格式:
如果有解决方案,输出n行,每行包含 3 个整数x,y,g,表示一次移动,每两个整数之间用一个空格隔开,其中(x ,y)表示要移动的方块的坐标,g 表示移动的方向,1 表示向右移动,-1−1表示向左移动。注意:多组解时,按照xx为第一关健字,yy为第二关健字,11优先于-1−1 ,给出一组字典序最小的解。游戏界面左下角的坐标为(0 ,0)。
如果没有解决方案,输出一行,包含一个整数-1。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 const int maxn=17; 8 int n; 9 int mp[maxn][maxn],bef[maxn][maxn][maxn],tp[maxn]; 10 bool qu[maxn][maxn],fih; 11 struct Ans{ 12 int x,y,f; 13 }ans[maxn]; 14 void cpy(int stp){ 15 for(int i=0;i<5;i++) 16 for(int j=0;j<7;j++) 17 bef[stp][i][j]=mp[i][j]; 18 } 19 void update(){ 20 for(int i=0;i<5;i++){ 21 int num=0; 22 for(int j=0;j<7;j++){ 23 if(!mp[i][j]) num++; 24 else if(num!=0){ 25 mp[i][j-num]=mp[i][j];mp[i][j]=0; 26 } 27 } 28 } 29 } 30 bool clr(){ 31 memset(qu,false,sizeof(qu));bool flag=false; 32 for(int i=0;i<5;i++){ 33 for(int j=0;j<7;j++){ 34 if(i-1>=0&&i+1<5){ 35 if(mp[i][j]&&mp[i-1][j]==mp[i][j]&&mp[i+1][j]==mp[i][j]){ 36 qu[i][j]=true;qu[i+1][j]=true;qu[i-1][j]=true;flag=true; 37 } 38 } 39 if(j-1>=0&&j+1<7){ 40 if(mp[i][j]&&mp[i][j-1]==mp[i][j]&&mp[i][j+1]==mp[i][j]){ 41 qu[i][j]=true;qu[i][j-1]=true;qu[i][j+1]=true;flag=true; 42 } 43 } 44 } 45 } 46 if(!flag) return false; 47 for(int i=0;i<5;i++) 48 for(int j=0;j<7;j++) 49 if(qu[i][j]) mp[i][j]=0; 50 return true; 51 } 52 void move(int x,int y,int f){ 53 int tmp=mp[x][y]; 54 mp[x][y]=mp[x+f][y];mp[x+f][y]=tmp; 55 update(); 56 while(clr()) update(); 57 } 58 bool check(){ 59 for(int i=0;i<5;i++) 60 for(int j=0;j<7;j++) 61 if(mp[i][j]) return false; 62 return true; 63 } 64 void dfs(int stp){ 65 if(check()){ 66 for(int i=0;i<stp;i++){ 67 cout<<ans[i].x<<" "<<ans[i].y<<" "<<ans[i].f<<endl; 68 } 69 fih=true; 70 } 71 if(stp>=n) return; 72 cpy(stp); 73 for(int i=0;i<5;i++){ 74 for(int j=0;j<7;j++){ 75 if(!mp[i][j]) continue; 76 if(i+1<5&&mp[i+1][j]!=mp[i][j]){ 77 move(i,j,1); 78 ans[stp]=(Ans){i,j,1}; 79 dfs(stp+1);if(fih) return; 80 ans[stp]=(Ans){0,0,0}; 81 for(int i=0;i<5;i++) 82 for(int j=0;j<7;j++) 83 mp[i][j]=bef[stp][i][j]; 84 } 85 if(i-1>=0&&mp[i-1][j]==0){ 86 move(i,j,-1); 87 ans[stp]=(Ans){i,j,-1}; 88 dfs(stp+1);if(fih) return; 89 ans[stp]=(Ans){0,0,0}; 90 for(int i=0;i<5;i++) 91 for(int j=0;j<7;j++) 92 mp[i][j]=bef[stp][i][j]; 93 } 94 } 95 } 96 } 97 int main(){ 98 cin>>n; 99 for(int i=0;i<5;i++){ 100 cin>>mp[i][tp[i]]; 101 while(mp[i][tp[i]]!=0){ 102 tp[i]++;cin>>mp[i][tp[i]]; 103 } 104 } 105 dfs(0); 106 if(ans[0].f==0) cout<<-1<<endl; 107 return 0; 108 }
考试的时候要有文件输入输出,所以不能直接exit(0)要回溯的时候进行判断
这个qu数组真的很妙,巧妙地解决了超过3个连续喝交叉连续的问题
以后的模拟题争取自己做出来
做模拟题要有想法
作业调度方案
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 const int maxn=27; 8 const int maxm=1e6+7; 9 int n,m,ans; 10 int en_gong[maxn],en_ji[maxn],num[maxn],ji[maxn][maxn],shi[maxn][maxn],a[maxn*maxn]; 11 bool yong[maxn][maxm]; 12 int main(){ 13 //freopen("a.in","r",stdin); 14 cin>>m>>n; 15 for(int i=1;i<=n*m;i++) cin>>a[i]; 16 for(int i=1;i<=n;i++) 17 for(int j=1;j<=m;j++) 18 cin>>ji[i][j]; 19 for(int i=1;i<=n;i++) 20 for(int j=1;j<=m;j++) 21 cin>>shi[i][j]; 22 for(int i=1;i<=n*m;i++){ 23 int JI=ji[a[i]][++num[a[i]]]; 24 int SHI=shi[a[i]][num[a[i]]]; 25 bool flag,reach=false;; 26 for(int j=en_gong[a[i]]+1;j<=en_ji[JI];j++){ 27 flag=true; 28 for(int k=j;k<j+SHI;k++){ 29 if(yong[JI][k]){ 30 flag=false;break; 31 } 32 } 33 if(flag){ 34 for(int k=j;k<j+SHI;k++) yong[JI][k]=true; 35 en_gong[a[i]]=j+SHI-1;reach=true;break; 36 } 37 } 38 if(!reach){ 39 int st=max(en_ji[JI]+1,en_gong[a[i]]+1); 40 for(int j=st;j<st+SHI;j++) yong[JI][j]=true; 41 en_gong[a[i]]=st+SHI-1;en_ji[JI]=st+SHI-1; 42 } 43 } 44 for(int i=1;i<=m;i++) ans=max(ans,en_ji[i]); 45 cout<<ans<<endl; 46 }