斗地主 && 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-414 来表示;小王的表示方法为 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 表示向右移动,-11表示向左移动。注意:多组解时,按照xx为第一关健字,yy为第二关健字,11优先于-11 ,给出一组字典序最小的解。游戏界面左下角的坐标为(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 }

 

posted @ 2018-10-30 18:35  lcan  阅读(289)  评论(0编辑  收藏  举报