这篇博客是在看到一篇评论发的
1.骗分的适用范围
众所周知,骗分或打表这在比赛中还是很有用的;
但如果你不知道如何正确地去骗分或打表,会导致你错失很多分数;
适用范围:
1.在你遇到一点都不会的题时题面看着也能搜索时,你就可以试试DFS骗分了
2.或者是遇到不会的题时数据也很小,比如n<=30或n<=50等,你就可以考虑用打表做了
3.小技巧:在遇到[USACO]这个东西时,你直接输出样例就有分
2.题目示范
1.暴力搜索骗分
这道题十分的像搜索,所以天真的我便拿搜索写了这道题;
代码:
#include<bits/stdc++.h>
using namespace std;
struct ys{
int q,w,t,s;
};
int n,m,dt[1007][1007],x,y,z,dx,dy,mv[5][2]={{0,0},{1,0},{0,1},{-1,0},{0,-1}},ans;
bool vis[1007][1007];
ys k;
queue<ys>q;
int main() {
memset(dt,-1,sizeof dt);
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>z>>x>>y;
dt[x][y]=z;
}
q.push(ys{1,1,0,0});
if(dt[1][1]==0){
ans++;
}
vis[1][1]=true;
while(!q.empty()){
k=q.front();
ans=max(k.s,ans);
q.pop();
for(int i=1;i<=4;i++){
dx=k.q+mv[i][0];
dy=k.w+mv[i][1];
if(dx<1||dy<1||dx>n||dy>n||vis[dx][dy]){
continue;
}
vis[dx][dy]=true;
if(dt[dx][dy]>=k.t){
q.push(ys{dx,dy,dt[dx][dy],k.s+1});
}
q.push(ys{dx,dy,k.t+1,k.s});
}
}
cout<<ans;
return 0;
}
但我又看见了这个:而机器人每一时刻只能够移动一格或停留在原地不动;
然后结果也是惨不忍睹:
而这道题的正解为dp;
这也启示了我们,你不会dp也能拿分,而在考场上这10分可能是至关重要的;
正解:你需要用当前这个序号的鼹鼠为结尾求可以打死鼹鼠的最大数;
代码:
#include<bits/stdc++.h>
using namespace std;
struct ys{
int x,y,t;
};
int n,m,f[10007],ans;
ys a[10007];
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i].t>>a[i].x>>a[i].y;//一定先是t
}
for(int i=1;i<=m;i++){
f[i]=1;
for(int j=i-1;j>=1;j--){
if(abs(a[i].x-a[j].x)+abs(a[i].y-a[j].y)<=a[i].t-a[j].t){//看时间够不够
f[i]=max(f[i],f[j]+1);//求最大值
}
}
ans=max(f[i],ans);//求最大值
}
cout<<ans;
return 0 ;
}
可见,虽然dp难但骗一点分还是很容易的;
2.打表得分
题目十分的通俗易懂,直接使用DFS大法!!!
于是5min写的代码便新鲜出炉了:
#include<bits/stdc++.h>
using namespace std;
long long n,ans,num;
bool vis[45];
void dfs(int x,int y){//x是当前拿的数的总和,y是上一个拿的数
if(x==num){
ans++;
return;
}
for(int i=y+1;i<=n;i++){//不能取比前一个大的
if(x+i>num){
continue;
}
dfs(x+i,i);
}
return;
}
int main() {
cin>>n;
num=(n*n+n)/4;//把总和分成两部分
dfs(0,0);
cout<<ans/2;//去重
return 0;
}
虽然答案正确,但时间复杂度:
30
4339640
--------------------------------
Process exited after 2.987 seconds with return value 0
请按任意键继续. . .
通过不了;
于是我绞尽脑汁想到了打表,就是把每个答案都搜出来并存起来
虽然说:
39
1512776590
--------------------------------
Process exited after 1800 seconds with return value 0
请按任意键继续. . .
但O(1)的时间复杂度保证了我不会超时;
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,a[45]={0,0,1,1,1,1,2,4,7,11,20,35,62,110,198,361,657,1205,2220,4110,7636,14230,26610,49910,93846,176871,334136,632602,1199892,2279914,4339640,8273610,15796439,30200344,57816630,110826888,212681976,408587849,785794088,1512776590};
int main() {
cin>>n;
if((n*n+n)%4!=0){
cout<<0;
}else{
cout<<a[n];
}
return 0;
}
3.总结
我通过一系列骗分总结出了经验:
只要学好DFS不管什么题都能拿亿点分(骗分很重要);
祝点赞的人都能成为骗分圣体!!!^_^