专栏文章
以 P7147 为例,记录一下 MatrixGroup 的当前码风
个人记录参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @minl2b32
- 此快照首次捕获于
- 2025/12/02 04:09 3 个月前
- 此快照最后确认于
- 2025/12/02 04:09 3 个月前
CPP
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0,del##i##verme=int(n);i<del##i##verme;++i)
#define rep1(i,n) for(int i=1,parano##i##a=int(n);i<=parano##i##a;++i)
#define per(i,n) for(int i=int(n)-1;i>=0;--i)
#define per1(i,n) for(int i=int(n);i>=1;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define y0 LingLuo
#define y1 VividCycle
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using namespace std;
const ll mod1=998244353;
const ll mod2=1000000007;
unsigned time_related_rand()
{
return unsigned(std::chrono::steady_clock::now().time_since_epoch().count());
}
const int clockwise=0,counterclockwise=1;
const string hai_name[37]={
"1M","2M","3M","4M","5M","6M","7M","8M","9M",
"1P","2P","3P","4P","5P","6P","7P","8P","9P",
"1S","2S","3S","4S","5S","6S","7S","8S","9S",
"E","S","W","N","B","F","Z","DOUBLE","REVERSE","PASS"};
const int type[37]={
0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,4,5,6};
const int val[37]={
1,2,3,4,5,6,7,8,9,
1,2,3,4,5,6,7,8,9,
1,2,3,4,5,6,7,8,9,
101,104,107,110,113,116,119,0,0,0};
int cnt[38];
bool agari_without_atama_chinitsu(int *valt)
{
int p=0,q=0;
rep(i,9)
{
if(valt[i]<p+q) return false;
int c=valt[i]-p-q;
p=q;q=c%3;
}
return p==0&&q==0;
}
bool agari_without_atama()
{
for(int i=27;i<34;++i) if(cnt[i]%3) return false;
return agari_without_atama_chinitsu(cnt)
&&agari_without_atama_chinitsu(cnt+9)
&&agari_without_atama_chinitsu(cnt+18);
}
bool agari(vector<int> vc)
{
if(int(vc.size())%3!=2)
{
cout<<"WHY DO I NEED DETERMINE WHETHER A TEHAI WITH "<<vc.size()<<" HAI(S) IS AGARI?"<<endl;
exit(-1);
}
sort(vc.begin(),vc.end());
if(vc.back()>=34) return false;
memset(cnt,0,sizeof(cnt));
for(int x:vc) ++cnt[x];
rep(i,34) if(cnt[i]>=2)
{
cnt[i]-=2;
if(agari_without_atama()) return true;
cnt[i]+=2;
}
return false;
}
int dp[2][5][3][3],nw[2][5][3][3];
int shantensu(vector<int> vc)
{
int n=int(vc.size())/3;
memset(cnt,0,sizeof(cnt));
for(int x:vc) ++cnt[x];
memset(dp,0x3f,sizeof(dp));
dp[0][0][0][0]=0;
rep(i,34)
{
memset(nw,0x3f,sizeof(nw));
rep(j,2) rep(k,n+1) rep(l,3) rep(m,3) if(dp[j][k][l][m]!=0x3f3f3f3f)
{
for(int c=l+m;c<=4;++c)
{
int need=max(0,c-cnt[i]);
int rest=c-l-m;
if(k+l+m+rest%3+rest/3<=n)
nw[j][k+l+rest/3][m][rest%3]=min(nw[j][k+l+rest/3][m][rest%3],dp[j][k][l][m]+need);
if(j==0&&rest>=2&&k+l+m+rest-2<=n)
nw[1][k+l][m][rest-2]=min(nw[1][k+l][m][rest-2],dp[0][k][l][m]+need);
}
}
if(val[i]==9||type[i]==3)
{
memset(dp,0x3f,sizeof(dp));
rep(j,2) rep(k,5) dp[j][k][0][0]=nw[j][k][0][0];
}
else
{
memcpy(dp,nw,sizeof(dp));
}
}
return dp[1][n][0][0];
}
const char player_name[4]={'A','B','C','D'};
const int no_buff=0,skipped=1,no_draw=2;
int state[4]={0,0,0,0};
int direction=clockwise,current_player=0;
const int nxt[2][4]={1,2,3,0,3,0,1,2};
vector<int> tehai[4];int shanten[4];
vector<int> temp;
void draw()
{
cout<<"DRAW"<<endl;
exit(0);
}
void calcshanten(int player)
{
shanten[player]=shantensu(tehai[player]);
}
void selfdrawn(int player)
{
cout<<player_name[player]<<" SELFDRAWN"<<endl;
cout<<player_name[player]<<" WIN"<<endl;
exit(0);
}
void ron(int player)
{
cout<<player_name[player]<<" RON"<<endl;
cout<<player_name[player]<<" WIN"<<endl;
exit(0);
}
int counter;
void drawcard(int player)
{
if(counter==148)
{
draw();
}
string st;cin>>st;++counter;
int x=0;rep(i,37)if(st==hai_name[i]){x=i;break;}
tehai[player].pb(x);
cout<<player_name[player]<<" IN "<<st<<endl;
}
void play(int player,int card)
{
tehai[player].erase(find(tehai[player].begin(),tehai[player].end(),card));
if(card!=36)
cout<<player_name[player]<<" OUT "<<hai_name[card]<<endl;
else
cout<<player_name[player]<<" OUT "<<hai_name[card]<<" "<<
player_name[nxt[direction][current_player]]<<endl;
}
bool check_furo(int player,int card,int w1,int w2,string furo_type)
{
temp=tehai[player];
vector<int>::iterator itr=find(temp.begin(),temp.end(),w1);
if(itr==temp.end()) return false;
temp.erase(itr);
itr=find(temp.begin(),temp.end(),w2);
if(itr==temp.end()) return false;
temp.erase(itr);
int stv=shantensu(temp);
if(stv>=shanten[player]) return false;
tehai[player]=temp;shanten[player]=stv;
if(card<w1) swap(card,w1);
if(card>w2) swap(card,w2);
cout<<player_name[player]<<" "<<furo_type<<" "<<hai_name[w1]<<" "<<
hai_name[card]<<" "<<hai_name[w2]<<endl;
return true;
}
void tsuzuku()
{
current_player=nxt[direction][current_player];
}
int to_play()// nankiru
{
int x=114541,ret=0;
rep(i,tehai[current_player].size())
{
if(i==0||tehai[current_player][i]!=tehai[current_player][i-1])
{
temp=tehai[current_player];temp.erase(temp.begin()+i);
int z=shantensu(temp);
if(z<=x)
{
x=z;ret=tehai[current_player][i];
}
}
}
return ret;
}
int main()
{
rep(i,13)
{
drawcard(0);drawcard(1);drawcard(2);drawcard(3);
}
rep(i,4) calcshanten(i);
while(1)
{
if(state[current_player]==skipped)
{
state[current_player]=no_buff;
tsuzuku();
continue;
}
if(state[current_player]==no_buff)
{
drawcard(current_player);
}
state[current_player]=no_buff;
sort(tehai[current_player].begin(),tehai[current_player].end());
if(agari(tehai[current_player]))
{
selfdrawn(current_player);
}
if(tehai[current_player].back()==36)// pass
{
play(current_player,36);
state[nxt[direction][current_player]]=skipped;
calcshanten(current_player);
tsuzuku();
continue;
}
if(tehai[current_player].back()==35)// reverse
{
play(current_player,35);
direction^=1;
calcshanten(current_player);
tsuzuku();
continue;
}
if(tehai[current_player].back()==34)// double
{
play(current_player,34);
calcshanten(current_player);
continue;
}
int sutehai=to_play();
play(current_player,sutehai);
calcshanten(current_player);
int potential_ron=nxt[direction][current_player];
while(potential_ron!=current_player)
{
temp=tehai[potential_ron];temp.pb(sutehai);
if(agari(temp))
{
ron(potential_ron);
}
potential_ron=nxt[direction][potential_ron];
}
bool flag=false;
rep(i,4) if(i!=current_player&&check_furo(i,sutehai,sutehai,sutehai,"PONG"))
{
current_player=i;state[i]=no_draw;
flag=true;break;
}
if(flag) continue;
if(type[sutehai]<=2)
{
int nxt_player=nxt[direction][current_player];
int value=val[sutehai];
if(value<=7&&check_furo(nxt_player,sutehai,sutehai+1,sutehai+2,"CHOW"))
{
current_player=nxt_player;state[current_player]=no_draw;
continue;
}
if(value<=8&&value>=2&&check_furo(nxt_player,sutehai,sutehai-1,sutehai+1,"CHOW"))
{
current_player=nxt_player;state[current_player]=no_draw;
continue;
}
if(value>=3&&check_furo(nxt_player,sutehai,sutehai-2,sutehai-1,"CHOW"))
{
current_player=nxt_player;state[current_player]=no_draw;
continue;
}
}
tsuzuku();
}
return 0;
}
/* things to check
1. int overflow or long long memory need
2. recursion/array/binary search/dp/loop bounds
3. precision
4. special cases(n=1,bounds)
5. delete debug statements
6. initialize(especially multi-tests)
7. = or == , n or m ,++ or -- , i or j , > or >= , < or <=
8. keep it simple and stupid
9. do not delete, use // instead
10. operator priority
11. is there anything extra to output?
12. ...
*/
/* something to think about
1. greedy? dp? searching? dp with matrix/ segment tree? binary search?
2. If contains "not", why not ?????? or few affect?
*/
稍微解释一下,如果一行代码在编辑器里超过一行了就会分行。
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...