zoukankan      html  css  js  c++  java
  • 斗地主 && Mayan游戏 && 作业调度方案

    斗地主

    题目描述

    牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的AA到KK加上大小王的共5454张牌来进行的扑克牌游戏。在斗地主中,牌的大小关 系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2< ext{小王}< ext{大王}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
    ",ans);
    145   }
    146   return 0;
    147 } 

     Mayan游戏

    题目描述

    Mayan puzzle是最近流行起来的一个游戏。游戏界面是一个77 行 imes 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 }
  • 相关阅读:
    VC 常见问题百问
    python windows 环境变量
    Check server headers and verify HTTP Status Codes
    Where are the AES 256bit cipher suites? Please someone help
    outlook 如何预订会议和会议室
    安装Axis2的eclipse插件后,未出现界面
    windows 环境变量
    python 时间日期处理汇集
    openldap学习笔记(使用openldap2.3.32)
    set p4 environment in windows
  • 原文地址:https://www.cnblogs.com/lcan/p/9878664.html
Copyright © 2011-2022 走看看