大意不再赘述。
思路:我思考了好久,最终还是没想出来,去网上搜了搜解题报告,发现大多是似是而非的观点,于是把自己的想法写出来。
我们把Stan取石子记为0,Ollie取记为1。以第一组测试数据为例: 20 3 1 3 8
如果Stan想赢,则20的标记应该是0,我们以f[20] = 0,表示Stan取的第20颗石子,依次类推。
那么20的前态:19 17 15,则三个数之间必须有一个f值为1才可以,因为只要f[19] || f[17] || f[15] = 1,那么f[20]就可以等于0,因为题目满足最优子结构,而且Ollie取过其中的一个,Stan一定会取第20个石子,那么Stan wins,反之,Ollie wins,其他的子状态依次类推,最后我们最后只要判断f[n]是否为0即可。
另外:把a数组赋值为1,题目如果是Ollie先取呢?由于两者的状态相同,我们把输出改一下即可。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int stone[11];
int a[1000100];
int n, m;
char sw[20] = "Stan wins\n";
char ow[20] = "Ollie wins\n";
void init()
{
memset(a, 1, sizeof(a));
}
void dp()
{
for(int i = 0; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(a[i])
{
a[i+stone[j]] = 0;
}
}
}
if(a[n] == 0) printf("%s", sw);
else printf("%s", ow);
}
void read_case()
{
init();
scanf("%d", &m);
for(int i = 1; i <= m; i++)
{
scanf("%d", &stone[i]);
}
}
void solve()
{
read_case();
dp();
}
int main()
{
while(~scanf("%d", &n))
{
solve();
}
return 0;
}