POJ 1143

最开始DP思路大方向是对的,但是一直苦于状态不知道怎么表示。

略览下题解思路,状态压缩,用是经常用,之前也联系过,实战上还是显出生疏了,对这么常用的技巧竟然一时没想起来

真正写代码的时候也磕磕绊绊debug了很久,一边怕数组越界,一边担心数组开爆,但最后数组还是开小了,RUNTIMEERROR好久

还是差的很多,继续提升吧

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxn= 25;
const int maxs= 21;

int a[maxn];
bool ck[maxn];
bool dv[(1<<maxs)+5], vis[(1<<maxs)+5];
int n;

bool DP(int st)
{
	if (vis[st]){
		return dv[st];
	}

	int lose= 1;
	for (int i= 0; i< n && lose; ++i){
		if (!ck[a[i]]){
			continue;
		}
		int t_st= st ^ (1<<a[i]);
		ck[a[i]]= 0;
		int drop= 0;
		drop|= (1<<i);
		for (int j= i+1; j< n; ++j){
			if (!ck[a[j]]){
				continue;
			}
			int flag= 1;
			if (0== a[j]%a[i]){
				flag= 0;
			}
			for (int p= a[j]-a[i]; p> 1 && flag; p-= a[i]){
				if (!ck[p]){
					flag= 0;
				}
			}
			if (!flag){
				t_st^= (1<<a[j]);
				ck[a[j]]= 0;
				drop|= (1<<j);
			}
		}

		if (!DP(t_st)){
			lose= 0;
		}
		vis[t_st]= 1;
		for (int k= i; k< n; ++k){
			if (drop & (1<<k)){
				ck[a[k]]= 1;
			}
		}
	}

	vis[st]= 1;
	return dv[st]= lose ? 0 : 1;
}
int main(int argc, char const *argv[])
{
	int kase= 0;
	while (~scanf("%d" ,&n) && n){
		vector<int> ans;
		memset(ck, 0 ,sizeof(ck));
		memset(vis, 0, sizeof(vis));
		int st= 0;
		for (int i= 0; i< n; ++i){
			scanf("%d", a+i);
			ck[a[i]]= 1;
			st|= (1<<a[i]);
		}
		sort(a, a+n);

		dv[0]= 0;
		vis[0]= 1;
		for (int i= 0; i< n; ++i){
			int t_st= st ^ (1<<a[i]);
			int drop= 0;
			ck[a[i]]= 0;
			drop|= (1<<i);
			for (int j= i+1; j< n; ++j){
				int flag= 1;
				if (0== a[j]%a[i]){
					flag= 0;
				}
				for (int p= a[j]-a[i]; p> 1 && flag; p-= a[i]){
					if (!ck[p]){
						flag= 0;
					}
				}
				if (!flag){
					t_st^= (1<<a[j]);
					ck[a[j]]= 0;
					drop|= 1<<j;
				}
			}

			if (!DP(t_st)){
				ans.push_back(a[i]);
			}
			vis[t_st]= 1;
			for (int k= i; k< n; ++k){
				if (drop & (1<<k)){
					ck[a[k]]= 1;
				}
			}
		}
		printf("Test Case #%d\n", ++kase);
		if (ans.empty()){
			printf("There's no winning move.");
		}
		else{
			printf("The winning moves are:");
			int sz= ans.size();
			for (int i= 0; i< sz; ++i){
				printf(" %d", ans[i]);
			}
		}
		putchar('\n');
		putchar('\n');
	}
	return 0;
}
posted @ 2021-04-26 21:22  IdiotNe  阅读(39)  评论(0编辑  收藏  举报