[HNOI2013] 比赛 题解

[HNOI2013] 比赛 题解


分析

尝试记忆化爆搜 DP,然后加入剪枝:

  1. 可行性剪枝:

    当某队分数非常多,全胜也无法花完,那么延伸出去的所有状态都不合法。

  2. 减少状态数:

    把分数按大小排序,可以减少很多状态数。

代码

//#define Plus_Cat ""
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define RCL(a,b,c,d) memset(a,b,sizeof(c)*(d))
#define tomin(a,...) ((a)=min({(a),__VA_ARGS__}))
#define tomax(a,...) ((a)=max({(a),__VA_ARGS__}))
#define FOR(i,a,b) for(int i(a); i<=(int)(b); ++i)
#define DOR(i,a,b) for(int i(a); i>=(int)(b); --i)
#define EDGE(g,i,x,y) for(int i(g.h[x]),y(g[i].v); ~i; y=g[i=g[i].nxt].v)
using namespace std;
constexpr int N(10+10),B(31);

namespace IOEcat {
#define isD(c) ('0'<=(c)&&(c)<='9')
#define DE(...) E(#__VA_ARGS__,__VA_ARGS__)
	struct Icat {

		char getc() {
			return getchar();
		}

		template<class T>void operator ()(T &x) {
			static bool sign(0);
			static char ch(0);
			sign=0,x=0;
			while(ch=getc(),!isD(ch))if(ch=='-')sign=1;
			do x=(x<<1)+(x<<3)+(ch^48);
			while(ch=getc(),isD(ch));
			if(sign)x=-x;
		}

		template<class T,class...Types>void operator ()(T &x,Types&...args) {
			return (*this)(x),(*this)(args...);
		}

	} I;
	struct Ocat {

		void putc(char c) {
			putchar(c);
		}

		template<class T>void operator ()(T x,const char lst='\n') {
			static int top(0);
			static char st[100];
			if(x<0)x=-x,putc('-');
			do st[++top]=(x%10)^48,x/=10;
			while(x);
			while(top)putc(st[top--]);
			putc(lst);
		}

		template<class T,class...Types>void operator ()(const T x,const char lst='\n',const Types...args) {
			return (*this)(x,lst),(*this)(args...);
		}

	} O;
	struct Ecat {

		template<class T>void operator ()(const char *fmt,const T x) {
			cerr<<fmt<<':'<<x<<'.'<<endl;
		}

		template<class T,class...Types>void operator ()(const char *fmt,const T x,const Types...args) {
			while(*fmt^',')cerr<<*fmt++;
			return cerr<<':'<<x<<" ,",(*this)(++fmt,args...);
		}

	} E;

} using namespace IOEcat;

namespace Modular {
#define Mod 1000000007
	
	template<class T1,class T2>auto add(const T1 a,const T2 b) {
		return a+b>=Mod?a+b-Mod:a+b;
	}
	
	template<class T1,class T2>auto mul(const T1 a,const T2 b) {
		return (ll)a*b%Mod;
	}
	
	template<class T1,class T2>T1 &toadd(T1 &a,const T2 b) {
		return a=add(a,b);
	}
	
	template<class T1,class T2>T1 &tomul(T1 &a,const T2 b) {
		return a=mul(a,b);
	}
	
} using namespace Modular;

int n;
int a[N];
unordered_map<ull,int> f[N];

ull key(vector<int> vec) {
	ull h(0);
	sort(vec.begin(),vec.end());
	for(const int &x:vec)h=h*B+x;
	return h;
}

vector<int> val(ull h) {
	vector<int> vec(n,0);
	DOR(i,n-1,0)vec[i]=h%B,h/=B;
	return vec;
}

void dfs(unordered_map<ull,int> &F,vector<int> &now,const int &u,int v,const int &val) {
	if(now[u]>3*(n-v))return;
	if(v>=n) {
		if(!now[u])toadd(F[key(now)],val);
		return;
	}
	if(now[u]>=3)now[u]-=3,dfs(F,now,u,v+1,val),now[u]+=3;//win
	if(now[u]>=1&&now[v]>=1)--now[u],--now[v],dfs(F,now,u,v+1,val),++now[u],++now[v];//draw
	if(now[v]>=3)now[v]-=3,dfs(F,now,u,v+1,val),now[v]+=3;//lose
}

int main() {
#ifdef Plus_Cat
	freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
#endif
	I(n);
	FOR(i,1,n)I(a[i]);
	sort(a+1,a+n+1);
	vector<int> vec(a+1,a+n+1);
	f[0][key(vec)]=1;
	FOR(i,0,n-1)for(const pair<ull,int> &h:f[i]) {
		vector<int> now(val(h.first));
		dfs(f[i+1],now,i,i+1,h.second);
	}
	O(f[n][0],'\n');
	return 0;
}
posted @ 2025-01-22 10:53  Add_Catalyst  阅读(4)  评论(0)    收藏  举报