经典的DP+贪心题目
先用DP求出一个系统所能拦截的最大数量,然后用贪心求出拦截系统的最少数量即可。
要注意的是邻接矩阵的存储细节。对角线元素为0,若存在多种数据相同,不能看做有向图中的同一顶点。
先用DP求出一个系统所能拦截的最大数量,然后用贪心求出拦截系统的最少数量即可。
要注意的是邻接矩阵的存储细节。对角线元素为0,若存在多种数据相同,不能看做有向图中的同一顶点。
#include <stdio.h>
#include <string.h>
#define INF 0x7fffffff
int cnt;
int G[25][25];
int d[25];
int p[25];
int height[25];
int main()
{
int judge(int i);
int dp(int i);
int n,k,max,minh,res;
bool flag;
memset(d,0,sizeof(d));
memset(p,0,sizeof(p));
memset(G,0,sizeof(G));
cnt = 0;
max = 0;
res = 0;
while(scanf("%d",&n)!=EOF) //将每个数据都进行编号存储到邻接矩阵中。
{
k = judge(n);
for(int i = 0 ; i < cnt ; i++)
{
if( n <= d[i] && i != k) //注意邻接矩阵对角线上的数不为1.
{
G[i][k] = 1;
}
}
flag = false; //贪心算出最少拦截次数。
minh = INF;
for( int i = 0 ; i < res ; i++)
{
if(n <= height[i] && minh > height[i] - n)
{
minh = height[i] - n;
height[i] = n;
flag = true;
}
}
if(!flag)
{
height[res] = n;
res++;
}
}
for(int i = 0 ; i < cnt ; i++)
{
if(max < dp(i))
{
max = dp(i);
}
}
printf("%d %d\n",max,res);
return 0;
}
int judge(int n) //数据转化为序号存储。
{
d[cnt] = n;
return cnt++;
}
int dp(int i) //dp找一个可拦截的最大数。
{
int ans = p[i];
if(ans > 0) return ans;
ans = 1;
for(int j = 0 ; j < cnt ; j++)
{
if(G[i][j])
{
if(dp(j) +1 > ans)
{
ans = dp(j) + 1;
}
}
}
p[i] = ans;
return ans;
}