2017暑訓摸底(xdoj1045,xdoj1173,xdoj1007)


由於時間沒趕上摸底,只能跟一波新增的dp摸底,感覺難度一般般,可能有段時間內沒做題的緣故吧

暑訓就要開始了呢


黑白棋


思路:一上來就是個博弈搜索

根據上一狀態與這一狀態必勝必敗態的轉換來判斷先手的情況

dfs搜索所有前項狀態,若均為必敗態,則該狀態為必勝態,否則為必敗態


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;

int a[5][5];

int dfs(int x,int y)
{
int next[2][4]={{0,0,1,-1},{1,-1,0,0}};
int x1,y1,i,p=1;
for(i=0;i<4&&p==1;i++)
{
x1=x+next[0][i];
y1=y+next[1][i];
if(x1>=0&&y1>=0&&x1<5&&y1<5&&a[x1][y1]==0)
{
a[x1][y1]=1;
p=(dfs(x1,y1)+1)%2;
a[x1][y1]=0;
}
}
return p;
}

int main()
{
int i,j,t;
scanf("%d",&t);
while(t--)
{
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
scanf("%1d",&a[i][j]);
}
}
int p=0;
for(i=0;i<5&&p==0;i++)
{
for(j=0;j<5&&p==0;j++)
{
if(a[i][j]==0)
{
a[i][j]=1;
p=dfs(i,j);
a[i][j]=0;
}
}
}
if(p==0)
printf("lose\n");
else
printf("win\n");
}
return 0;
}



The most orz man

思路:sg值打表找規律

sg值:mex函數為下一狀態的sg值,則該狀態sg值為最小不屬於mex的非負整數

最終發現3的整數倍為必勝態,成功ac


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;
/*
const int maxn = 10010;

int sg[maxn];

void getSG(int a[],int n)//a為可能走法,n為所求sg數量
{
int i,j;
int temp[maxn];//存儲前項sg值,用於求mex
memset(sg,0,sizeof(sg));
for(i=0;i<n;i++)//依次求sg值
{
memset(temp,0,sizeof(temp));
for(j=0;i-a[j]>=0;j++)//j為可走步數
{
if(i<a[0])
break;
temp[sg[i-a[j]]]=1;
}
for(j=0;j<n;j++)
{
if(temp[j]==0)
{
sg[i]=j;
break;
}
}
}
}
*/
int main()
{
int n;
/*int a[maxn],t=1;
for(int i=0;i<70;i++)
{
a[i]=t;
t*=2;
if(t<0)
{
break;
}
}*/
while(scanf("%d",&n)!=EOF)
{
/*getSG(a,n);
for(int j=0;j<n;j++)
{
printf("%d %d\n",j,sg[j]);
}*/
if(n%3==0)
{
printf("No\n");
}
else
{
printf("Yes\n");
}
}
return 0;
}


易碎的鳥蛋

思路:典型的dp,以兩個題設變量雞蛋數n和樓層數m作為狀態變量,以所求結果最少實驗次數作為dp值,枚舉投放雞蛋的試驗樓層

可得到兩種情況,分為雞蛋破碎和未破碎

若雞蛋破碎,則繼續試驗較低樓層,但可用雞蛋數減一

若雞蛋未破,則繼續試驗較高樓樓層即可

兩種情況中較高的試驗次數作為該狀態的dp值,枚舉結果中取最低值進行轉移

轉移方程為dp[i][j]=min((max(dp[i-1][k-1],dp[i][j-k])+1),dp[i][j])


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;

const int maxn = 1e3+10;

int dp[maxn][maxn];

int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int j=0;j<=1000;j++)
{
dp[0][j]=0;
dp[1][j]=j;
dp[j][0]=0;
dp[j][1]=1;
}
for(int i=2;i<=n;i++)
{
for(int j=2;j<=m;j++)
{
dp[i][j]=dp[i-1][j];
for(int k=1;k<=j;k++)
{
dp[i][j]=min((max(dp[i-1][k-1],dp[i][j-k])+1),dp[i][j]);
}
}
}
printf("%d\n",dp[n][m]);
}
return 0;
}


最終摸底的結果還是可以接受的,全場第三,d題一開始總想着二分找最優狀態,后來發現不足10的數據量完全可以枚舉,或許利用計算機才是acm正確的姿勢吧


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com