Placing Lampposts------UVA10859-----DP
2013-07-22 20:04
309 查看
题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1800
题目意思:
给你N个点,M条边
你可以在一个点放灯,或者不放
要求,放尽量少的灯,使所有边亮,使同时被两盏灯照亮的边尽量多,要你输出灯数,被两个灯照亮的变数,只被一个灯照亮的灯数
解题思路:
优化目标有两个,使得灯数a尽量少,使得被两个灯的边数b尽量多
在这里可以转化一下,就是恰被一盏灯照亮的边数c尽量少
下面就是学到的东西了,当我们同时需要优化两个变量a,c,要求首先满足a最小的情况下,使得c尽量小
我们可以引入一个值x=Ma+c,在这里的M是一个很大的值,是一个比c的理论最大值和a的最小理论值之差还要大的值
为什么?因为如果两个a不同的,无论c相差多少,仍然是a起决定性的作用,实在是太聪明了
则我们的目标就是使x的值尽量小,那么x/M的整数部分就是灯数,x%M就是只被一个灯照亮的,m-x%M就是被两个灯照亮的
我们令dp[i][j]表示在i节点,如果j=1表示父亲节点放灯,0则反之,的x的最小值
那么对i来说,有两个决策
如果在i放灯
那么dp[i][j] = sum(dp[k][1])+M,如果j=0且i不是根的话,还要+1,因为i和他的父亲节点这条边只被一个灯照亮
如果在i不放灯,必须j=1(不然边就无法照亮)
那么dp[i][j] = sum(dp[k][0]),如果i不是根,还要加1,因为i和他的父亲节点这条边只被一个灯照亮
通过边DFS边DP的思路就可以把结果求出来
另外还要引入vis,因为这个里面可能不是联通的,那么可能有多棵树,而且加入vis还可以剪枝
下面上代码:
题目意思:
给你N个点,M条边
你可以在一个点放灯,或者不放
要求,放尽量少的灯,使所有边亮,使同时被两盏灯照亮的边尽量多,要你输出灯数,被两个灯照亮的变数,只被一个灯照亮的灯数
解题思路:
优化目标有两个,使得灯数a尽量少,使得被两个灯的边数b尽量多
在这里可以转化一下,就是恰被一盏灯照亮的边数c尽量少
下面就是学到的东西了,当我们同时需要优化两个变量a,c,要求首先满足a最小的情况下,使得c尽量小
我们可以引入一个值x=Ma+c,在这里的M是一个很大的值,是一个比c的理论最大值和a的最小理论值之差还要大的值
为什么?因为如果两个a不同的,无论c相差多少,仍然是a起决定性的作用,实在是太聪明了
则我们的目标就是使x的值尽量小,那么x/M的整数部分就是灯数,x%M就是只被一个灯照亮的,m-x%M就是被两个灯照亮的
我们令dp[i][j]表示在i节点,如果j=1表示父亲节点放灯,0则反之,的x的最小值
那么对i来说,有两个决策
如果在i放灯
那么dp[i][j] = sum(dp[k][1])+M,如果j=0且i不是根的话,还要+1,因为i和他的父亲节点这条边只被一个灯照亮
如果在i不放灯,必须j=1(不然边就无法照亮)
那么dp[i][j] = sum(dp[k][0]),如果i不是根,还要加1,因为i和他的父亲节点这条边只被一个灯照亮
通过边DFS边DP的思路就可以把结果求出来
另外还要引入vis,因为这个里面可能不是联通的,那么可能有多棵树,而且加入vis还可以剪枝
下面上代码:
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn = 1010; const int M = 2000; vector<int> ma[maxn]; bool vis[maxn][2]; int dp[maxn][2]; int n,m; int qdp(int i,int j,int fa) { if(vis[i][j]) return dp[i][j]; vis[i][j] = true; int &ans = dp[i][j]; //先在i这里放灯 ans = M; //再遍历所有的子树 for(int k=0;k<ma[i].size();k++) { if(ma[i][k] != fa) ans += qdp(ma[i][k],1,i); } if(j==0 && fa>=0) ans++; //再就是在i节点不放,前提条件就是父亲节点放了,或者i就是根 if(j || fa<0) { int ans2 = 0; for(int k=0;k<ma[i].size();k++) { if(ma[i][k] != fa) ans2 += qdp(ma[i][k],0,i); } if(fa>=0) ans2++; ans = min(ans,ans2); } return ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) ma[i].clear(); memset(vis,false,sizeof(vis)); int a,b; for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); ma[a].push_back(b); ma[b].push_back(a); } int ans = 0; for(int i=0;i<=n;i++) { if(!vis[i][0])//这里是遇到了一棵新的树,则就将i作为树根,那么他的的父亲节点就是-1 ans+=qdp(i,0,-1); } printf("%d %d %d\n",ans/M,m-ans%M,ans%M); } return 0; }
相关文章推荐
- UVa 10859 Placing Lampposts (树形DP)
- uva_10859_Placing Lampposts( 樹形DP )
- uva 10859 Placing Lampposts (树形dp)
- UVA--10859--Placing Lampposts--DP
- UVA-10859 - Placing Lampposts(树形DP)
- UVA 10859 Placing Lampposts(树上dp)
- UVA 10859 Placing Lampposts 树形DP
- UVa:10859 Placing Lampposts(树形DP)
- uva 10859 Placing Lampposts / Tree DP
- Placing Lampposts UVA - 10859(树形dp)
- UVA 10859 Placing Lampposts--树形dp
- UVA 10859 Placing Lampposts(树DP)
- Uva 10859 - Placing Lampposts 树形dp
- uva 10859 Placing Lampposts 树形dp
- Uva 10859 - Placing Lampposts 树形dp
- UVaLive 10859 Placing Lampposts (树形DP)
- uva 10859 Placing Lampposts (树形dp)
- UVA 10859 Placing Lampposts(树状DP)
- uva10859 - Placing Lampposts 无根树转有根树 DP
- uva 10859 Placing Lampposts,树形dp