【ZROI】【DP】【17 提高 5】石头剪刀布

博客讨论了一种优化的动态规划(DP)策略来解决石头剪刀布游戏问题。通过证明在任何时候,a、b、c三个状态之间的差值不会超过2,从而减少了状态树的规模,降低了时间复杂度到O(αn)。文章提供了相关代码实现。
摘要由CSDN通过智能技术生成

暴力DP可以定义 f[i][a][b][c] f [ i ] [ a ] [ b ] [ c ] 表示到第i个数为止,以0结尾的最长胜利序列长度为a,以1结尾的最长胜利序列长度为b,以2结尾的最长胜利序列长度为c的方案数,显然这样过于暴力了。接下来,我们会发现一个结论,那就是a,b,c任意两个数相差不超过2,证明如下:

由于石头的上一个必然是布,所以 c>=a1 c >= a − 1 ,同理, a>=b1 a >= b − 1 b>=c1 b >= c − 1 ,所以任意两个之间相差不会超过2.

这样,状态树就被大大压缩。

时间复杂度: O(αn)(α O ( α n ) ( α 为常数)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2006
#define tt 998244353
using namespace std;
int n,cnt,f[maxn][maxn][5][5];
bool vis[maxn][3];
int abs(int x){return (x>0)?x:-x;}
int main(){
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    scanf("%d",&n);getchar();
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++){
        char ch=getchar();
        while(ch!='\n'&&ch!=EOF)vis[i][ch-'0']=1,ch=getchar();
    }
    f[0][0][2][2]=1;
    for(int i=0;i<=n;i++)
     for(int p0=0;p0<=i;p0++)
      for(int j=-2;j<=min(2,i-p0);j++)
       for(int k=-2;k<=min(2,i-p0);k++) if(abs(j-k)<=2){
            int p,p1=p0+j,p2=p0+k;if(p1<0||p2<0)continue;
            if(vis[i+1][0])p=max(p0,p2+1),(f[i+1][p][p1-p+2][p2-p+2]+=f[i][p0][j+2][k+2])%=tt;
            if(vis[i+1][1])(f[i+1][p0][max(1,j)+2][k+2]+=f[i][p0][j+2][k+2])%=tt;
            if(vis[i+1][2])(f[i+1][p0][j+2][max(j+1,k)+2]+=f[i][p0][j+2][k+2])%=tt;
       }
    for(int i=1;i<=n;i++){
        cnt=0;
        for(int p0=i-2;p0<=i;p0++)
         for(int j=-2;j<=i-p0;j++)
          for(int k=-2;k<=i-p0;k++){
                int p1=p0+j,p2=p0+k;if(p0<0||p1<0||p2<0||(p0<i&&p1<i&&p2<i))continue;
                (cnt+=f[n][p0][j+2][k+2])%=tt;
          }
        printf("%d ",cnt);
    }
    return 0;
}
以下是一个简单的Android Studio石头剪刀布游戏的实现方法: 1.在布局文件中添加所需的控件,包括TextView、EditText、Button和ImageView等。 2.在Java代码中实现游戏逻辑,包括获取用户输入的手势、生成电脑随机手势、比较两个手势并输出结果等。 具体实现方法如下: 布局文件: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textLable" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="请输入您的手势:" android:textSize="20sp" android:layout_marginTop="50dp" android:layout_centerHorizontal="true"/> <EditText android:id="@+id/editText1" android:layout_width="200dp" android:layout_height="wrap_content" android:hint="请输入石头、剪刀或布" android:layout_below="@+id/textLable" android:layout_centerHorizontal="true" android:layout_marginTop="20dp"/> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确定" android:layout_below="@+id/editText1" android:layout_centerHorizontal="true" android:layout_marginTop="20dp"/> <ImageView android:id="@+id/imageView1" android:layout_width="100dp" android:layout_height="100dp" android:layout_below="@+id/button1" android:layout_centerHorizontal="true" android:layout_marginTop="20dp"/> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:layout_below="@+id/imageView1" android:layout_centerHorizontal="true" android:layout_marginTop="20dp"/> </RelativeLayout> ``` Java代码: ```java public class MainActivity extends AppCompatActivity { private EditText editText; private Button button; private ImageView imageView; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText) findViewById(R.id.editText1); button = (Button) findViewById(R.id.button1); imageView = (ImageView) findViewById(R.id.imageView1); textView = (TextView) findViewById(R.id.textView1); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String userGesture = editText.getText().toString(); String computerGesture = getComputerGesture(); int result = compareGesture(userGesture, computerGesture); showResult(result, computerGesture); } }); } // 生成电脑随机手势 private String getComputerGesture() { String[] gestures = {"石头", "剪刀", "布"}; int index = (int) (Math.random() * 3); return gestures[index]; } // 比较两个手势并输出结果 private int compareGesture(String userGesture, String computerGesture) { if (userGesture.equals(computerGesture)) { return 0; // 平局 } else if (userGesture.equals("石头") && computerGesture.equals("剪刀") || userGesture.equals("剪刀") && computerGesture.equals("布") || userGesture.equals("布") && computerGesture.equals("石头")) { return 1; // 用户胜利 } else { return -1; // 电脑胜利 } } // 显示结果 private void showResult(int result, String computerGesture) { int imageId; String resultText; switch (result) { case 0: imageId = R.drawable.pingju; resultText = "平局"; break; case 1: imageId = R.drawable.youwin; resultText = "您赢了"; break; case -1: imageId = R.drawable.youlose; resultText = "您输了"; break; default: imageId = R.drawable.pingju; resultText = "出错了"; break; } imageView.setImageResource(imageId); textView.setText("电脑出了" + computerGesture + "," + resultText); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值