1. 程式人生 > 實用技巧 >2020上海大學校賽H 紙牌遊戲(思維+暴力)

2020上海大學校賽H 紙牌遊戲(思維+暴力)

首先肯定是想著貪心選越大越好,問題是如何去檢查當前選這個是否滿足題意。我們可以對後面的進行判斷

已知當前的餘數是t,那麼我們要檢查3-t能否通過後面的組合選到,因為現在有3種數,我們考慮先固定一個數。

那麼剩下兩個數就是兩個變數,並且需要滿足兩個等式,因此我們可以將1個變數通過約束條件算出他的等式。

之後我們控制這個變數的列舉範圍看他能否成功。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
string s;
int ans[N];
int cnt[3];
int num[10]; bool check(int sign,int tot){ int i; int a=cnt[0],b=cnt[1],c=cnt[2]; int l=max(0,tot-b-c),r=min(a,tot);//0使用的範圍 for(i=l;i<=r;i++){ int y=((2*tot-2*i-sign)%3+3)%3;//1要滿足的條件 int l0=max(0,tot-i-c),r0=min(b,tot-i);//1使用的範圍 while(l0%3!=y) l0++; if(l0<=r0)
return true; } return false; } int main(){ ios::sync_with_stdio(false); int t,k; cin>>t; while(t--){ memset(cnt,0,sizeof cnt); memset(ans,0,sizeof ans); memset(num,0,sizeof num); int i; cin>>s>>k; int tmp=0;
for(i=0;i<(int)s.size();i++){ int sign=s[i]-'0'; cnt[sign%3]++; num[sign]++; } int id=0; for(i=9;i>=0&&id<k;i--){ while(id<k&&num[i]){ int sign=(i+tmp)%3; cnt[i%3]--,num[i]--; if(!check((3-sign)%3,k-id-1)){ cnt[i%3]++; num[i]++; break; } ans[++id]=i; tmp=sign; } } if((ans[1]==0&&id>1)||id<k){ cout<<-1<<endl; } else{ for(i=1;i<=k;i++) cout<<ans[i]; cout<<endl; } } }
View Code