LWYZ && ZQSZ 互测记录

此文为博主原创,转载...转载这种文章有意思吗qwq

严禁各OJ在未经博主同意的情况下擅自使用博文中的题面作为OJ题目。

这份题是莱芜一中@wyh大佬以及另外三个大佬出的来着...(我只认识wyh 233)

wyh:这份题在我们那里就是信心赛,你们人人都能AK的。

wyh:学姐把我的一句话题意魔改成了三千字小说...

我们这边考得惨不忍睹...

T1被出题人骗了 QAQ  T2一眼状压DP并不会做 QAQ  T3被魔改题面骗了 QAQ 

文末附上说好的题面读后感(然而我是拒绝的QAQ)。

 

A.

题目大意:

一个序列上共有n个点,两两之间形成一条线段。

任意选择其中 k 条线段,使得这 k 条线段的长度和最小。k 条线段的端点不能重合。

数据范围:

1<=n<=1000,1<=k<=n/2。

(wyh:原题范围是1000000,我这么良心给你们出了1000)

 

分析:

简单DP。dp[i][j][1/0]表示当前处理到了第i条线段,选择了j条线段,第i条线段选/不选的最小长度和。

原本我以为,这会是第一道我在考场上自己A掉的DP题,尽管它很水。

然而。wyh:我什么时候说过数据保证点的坐标有序啦。

于是忘记给n个点排序的我直接GG,爆零。(排完序就A了QAQ气哭)

AC代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<queue>
 5 
 6 const int MAXN = 1002;
 7 inline void read(int &x)
 8 {
 9     char ch = getchar(),c = ch;x = 0;
10     while(ch < '0' || ch > '9') c = ch,ch = getchar();
11     while(ch <= '9' && ch >= '0') x = (x<<1)+(x<<3)+ch-'0',ch = getchar();
12     if(c == '-') x = -x;
13 }
14 
15 int n,k,ans,num[MAXN],dis[MAXN];
16 int dp[MAXN][MAXN][2];
17 //dp[i][j][1/0]表示前i个数中选了j个数的最小和。 
18 //当前数不选,前一个数可选可不选
19 //当前数选,前一个数一定不选 
20 inline int Min(int a,int b)
21 {return a<b?a:b;}
22 
23 int main()
24 {
25     freopen("a.in","r",stdin);
26     freopen("a.out","w",stdout);
27     read(n),read(k);
28     for(int i = 1;i <= n;++ i)
29         read(num[i]);
30     std::sort(num+1,num+1+n);
31     for(int i = 2;i <= n;++ i)
32         dis[i-1] = num[i]-num[i-1];
33     memset(dp,0x3f,sizeof(dp));
34     -- n;
35     dp[0][0][0] = 0;
36     for(int i = 1;i <= n;++ i)
37     {
38         dp[i][0][0] = 0;
39         for(int j = 1;j <= Min(i,k);++ j)
40         {
41             dp[i][j][1] = dp[i-1][j-1][0]+dis[i];
42             dp[i][j][0] = Min(dp[i-1][j][0],dp[i-1][j][1]);
43 //            printf("%d %d %d %d\n",i,j,dp[i][j][1],dp[i][j][0]);
44         }
45     }
46     ans = Min(dp[n][k][0],dp[n][k][1]);
47     printf("%d\n",ans);
48     return 0;
49 }
A

 

B.

题目大意:

给定一个 n+1 个点(编号为 0,1,2 .. n)的有向图,求从0号点出发,经过所有城市至少一次,且最后回到0号点的最短路 。

数据范围:

1<=n<=15

分析:

数据范围已经非常明显了,这是个状压DP。

我不会状压DP!!!裸题也不会!!!(考前赶紧写几个压压惊)

先跑一遍Floyd,求出任意两点之间的最短路,然后DP。

dp[i][j]表示当前在i点,状态为j的最短路。

qwq直接把代码抄了一遍。抄完觉得状压DP也挺显然的...

接下来的qqxt游记里面还有几道状压DP,加油ww

AC代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 
 5 const int INF = 0x3f3f3f3f;
 6 inline void read(int &x)
 7 {
 8     char ch = getchar(),c = ch;x = 0;
 9     while(ch < '0' || ch > '9') c = ch,ch = getchar();
10     while(ch <= '9' && ch >= '0') x = (x<<1)+(x<<3)+ch-'0',ch = getchar();
11     if(c == '-') x = -x;
12 }
13 
14 int n,mx,ans;
15 int dis[20][20],dp[1<<16][20];
16 
17 inline int Max(int a,int b)
18 {return a>b?a:b;}
19 
20 inline int Min(int a,int b)
21 {return a<b?a:b;}
22 
23 int main()
24 {
25     freopen("b.in","r",stdin);
26     freopen("b.out","w",stdout);
27     read(n);
28     for(int i = 0;i <= n;++ i)
29         for(int j = 0;j <= n;++ j)
30             read(dis[i][j]);
31     for(int k = 0;k <= n;++ k)
32         for(int i = 0;i <= n;++ i)
33             for(int j = 0;j <= n;++ j)
34                 dis[i][j] = Min(dis[i][j],dis[i][k]+dis[k][j]);
35     memset(dp,0x3f,sizeof(dp));
36     dp[0][0] = 0;mx = (1<<n)-1;
37     for(int i = 0;i <= mx;++ i)
38         for(int j = 0;j <= n;++ j)
39             if(dp[i][j] != INF)
40                 for(int k = 0;k <= n;++ k)
41                     dp[i|(1<<k-1)][k] = Min(dp[i|(1<<k-1)][k],dp[i][j]+dis[j][k]);
42     ans = INF;
43     for(int i = 0;i <= n;++ i)
44         ans = Min(ans,dp[mx][i]+dis[i][0]);
45     printf("%d\n",ans);
46     return 0;
47 }
B

 

C.[SPJ]

题目大意:

给定n个点的坐标,要删除其中的k个,使得剩下的点两两之间欧几里得距离的最大值最小。

求删点的方案(输出任意一组即可)。

数据范围:

1<=n<=1000,1<=k<=30.

分析:

T3居然是个爆搜...NP问题...

听说出题人都不太会做  打死出题人

最大值最小,显然需要二分。二分mid,把所有距离大于mid的点连起来,转化为最小点覆盖问题。

wzy dalao:这可以贪心呀!【他真的用贪心把这道题A了%%%】

这道题的本意是要使用一个剪枝:如果某个点的度数为1,优先考虑删除与它相邻的点,结果不会更差。

所以我就写搜索了。今年又是很有可能考大爆搜的一年...

AC代码:

辣鸡std  太丑啦。改了好半天还是WA3个点,只好先这样了QAQ【趴】

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<ctime>
  5 
  6 const int MAXN = 1002;
  7 inline void read(int &x)
  8 {
  9     char ch = getchar(),c = ch;x = 0;
 10     while(ch < '0' || ch > '9') c = ch,ch = getchar();
 11     while(ch <= '9' && ch >= '0') x = (x<<1)+(x<<3)+ch-'0',ch = getchar();
 12     if(c == '-') x = -x;
 13 }
 14 
 15 int n,k,mx,l,r,mid,fr,ans,res,cnt,tot,find;
 16 int x[MAXN],y[MAXN],use[MAXN],q[MAXN];
 17 int del[MAXN],head[MAXN*MAXN*2];
 18 long long dis[MAXN][MAXN],notedis[MAXN*MAXN*2];
 19 inline int Max(int a,int b)
 20 {return a>b?a:b;}
 21 
 22 struct Edge
 23 {
 24     int f,t,v,nxt;
 25 }e[MAXN*MAXN*2];
 26 
 27 void insert(int f,int t,int v)
 28 {
 29     e[++cnt].f = f,e[cnt].t = t;
 30     e[cnt].v = v,e[cnt].nxt = head[f];
 31     head[f] = cnt;
 32 }
 33 
 34 void dfs(int now,int cnt)
 35 {
 36     if(cnt>k || ans) return;
 37     if(now > fr)
 38     {
 39         if(find)
 40         {
 41             bool outans = 0;
 42             for(int i = 1;i <= n;++ i)
 43                 if(del[i]){
 44                     printf("%d ",i);
 45                     outans = 1;
 46                 }
 47             if(!outans) printf("1");
 48         }
 49         ans = 1;
 50         return;
 51     }
 52     int top = q[now];
 53     if(del[top]) dfs(now+1,cnt);
 54     else
 55     {
 56         int tmp = cnt;
 57         for(int i = head[top];i;i = e[i].nxt)
 58         {
 59             int to = e[i].t;
 60             if(!del[to]) ++tmp,++del[to];
 61         }
 62         dfs(now+1,tmp);
 63         for(int i = head[top];i;i = e[i].nxt)
 64             del[e[i].t] --;
 65         if(use[top]!=1 && cnt+1<tmp)
 66         {
 67             del[top] = 1;
 68             dfs(now+1,cnt+1);
 69             del[top] = 0;
 70         }
 71     }
 72 }
 73 
 74 bool check(long long now)
 75 {
 76     memset(head,0,sizeof(head));
 77     memset(use,0,sizeof(use));
 78     memset(del,0,sizeof(del));
 79     fr = 0;ans = 0;cnt = 0;
 80     for(int i = 1;i < n;++ i)
 81         for(int j = i+1;j <= n;++ j)
 82             if(dis[i][j] >= now)
 83             {
 84                 insert(i,j,dis[i][j]);
 85                 insert(j,i,dis[i][j]);
 86                 if(!use[i]) q[++fr] = i;
 87                 if(!use[j]) q[++fr] = j;
 88                 use[i]++,use[j]++;
 89             }
 90     dfs(1,0);
 91     return ans;
 92 }
 93 
 94 int main()
 95 {
 96     freopen("c.in","r",stdin);
 97     freopen("c.out","w",stdout);
 98     read(n),read(k);
 99     for(int i = 1;i <= n;++ i)
100         read(x[i]),read(y[i]);
101     for(int i = 1;i < n;++ i)
102         for(int j = i+1;j <= n;++ j)
103         {
104             dis[i][j] = 1LL*(x[i]-x[j])*(x[i]-x[j])+1LL*(y[i]-y[j])*(y[i]-y[j]);
105             notedis[++tot] = dis[i][j];
106         }
107     std::sort(notedis+1,notedis+1+tot);
108     notedis[++tot] = notedis[tot-1]+1;
109     tot = std::unique(notedis+1,notedis+tot+1)-notedis-1;
110     
111     l = 1,r = tot;
112     while(l <= r)
113     {
114         mid = (l+r)>>1;
115         if(check(notedis[mid])) r = mid-1,res = mid;
116         else l = mid+1;
117     }        
118     find = true;
119     check(notedis[res]);
120     return 0;
121 }
C

 

 

 

题面读后感【我知道你们不会喜欢的所以我把它叠起来了】

“我所言者绝非善类。”
“我所见者亦非虚妄。” 

我是真的没读懂啊QAQ太高深啦...
我好菜啊

 

posted @ 2017-11-07 17:07 超时空灰狼菌 阅读(...) 评论(...) 编辑 收藏